diff options
Diffstat (limited to 'fs/cifs/inode.c')
| -rw-r--r-- | fs/cifs/inode.c | 237 |
1 files changed, 184 insertions, 53 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 53cce8cc2224..94979309698a 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -52,7 +52,7 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) | |||
| 52 | 52 | ||
| 53 | 53 | ||
| 54 | /* check if server can support readpages */ | 54 | /* check if server can support readpages */ |
| 55 | if (cifs_sb->tcon->ses->server->maxBuf < | 55 | if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf < |
| 56 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) | 56 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) |
| 57 | inode->i_data.a_ops = &cifs_addr_ops_smallbuf; | 57 | inode->i_data.a_ops = &cifs_addr_ops_smallbuf; |
| 58 | else | 58 | else |
| @@ -288,8 +288,8 @@ int cifs_get_file_info_unix(struct file *filp) | |||
| 288 | struct cifs_fattr fattr; | 288 | struct cifs_fattr fattr; |
| 289 | struct inode *inode = filp->f_path.dentry->d_inode; | 289 | struct inode *inode = filp->f_path.dentry->d_inode; |
| 290 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 290 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
| 291 | struct cifsTconInfo *tcon = cifs_sb->tcon; | ||
| 292 | struct cifsFileInfo *cfile = filp->private_data; | 291 | struct cifsFileInfo *cfile = filp->private_data; |
| 292 | struct cifsTconInfo *tcon = tlink_tcon(cfile->tlink); | ||
| 293 | 293 | ||
| 294 | xid = GetXid(); | 294 | xid = GetXid(); |
| 295 | rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); | 295 | rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); |
| @@ -313,15 +313,21 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
| 313 | FILE_UNIX_BASIC_INFO find_data; | 313 | FILE_UNIX_BASIC_INFO find_data; |
| 314 | struct cifs_fattr fattr; | 314 | struct cifs_fattr fattr; |
| 315 | struct cifsTconInfo *tcon; | 315 | struct cifsTconInfo *tcon; |
| 316 | struct tcon_link *tlink; | ||
| 316 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 317 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 317 | 318 | ||
| 318 | tcon = cifs_sb->tcon; | ||
| 319 | cFYI(1, "Getting info on %s", full_path); | 319 | cFYI(1, "Getting info on %s", full_path); |
| 320 | 320 | ||
| 321 | tlink = cifs_sb_tlink(cifs_sb); | ||
| 322 | if (IS_ERR(tlink)) | ||
| 323 | return PTR_ERR(tlink); | ||
| 324 | tcon = tlink_tcon(tlink); | ||
| 325 | |||
| 321 | /* could have done a find first instead but this returns more info */ | 326 | /* could have done a find first instead but this returns more info */ |
| 322 | rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, | 327 | rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, |
| 323 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 328 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
| 324 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 329 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 330 | cifs_put_tlink(tlink); | ||
| 325 | 331 | ||
| 326 | if (!rc) { | 332 | if (!rc) { |
| 327 | cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); | 333 | cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); |
| @@ -332,6 +338,13 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
| 332 | return rc; | 338 | return rc; |
| 333 | } | 339 | } |
| 334 | 340 | ||
| 341 | /* check for Minshall+French symlinks */ | ||
| 342 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { | ||
| 343 | int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid); | ||
| 344 | if (tmprc) | ||
| 345 | cFYI(1, "CIFSCheckMFSymlink: %d", tmprc); | ||
| 346 | } | ||
| 347 | |||
| 335 | if (*pinode == NULL) { | 348 | if (*pinode == NULL) { |
| 336 | /* get new inode */ | 349 | /* get new inode */ |
| 337 | cifs_fill_uniqueid(sb, &fattr); | 350 | cifs_fill_uniqueid(sb, &fattr); |
| @@ -353,7 +366,8 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
| 353 | int rc; | 366 | int rc; |
| 354 | int oplock = 0; | 367 | int oplock = 0; |
| 355 | __u16 netfid; | 368 | __u16 netfid; |
| 356 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 369 | struct tcon_link *tlink; |
| 370 | struct cifsTconInfo *tcon; | ||
| 357 | char buf[24]; | 371 | char buf[24]; |
| 358 | unsigned int bytes_read; | 372 | unsigned int bytes_read; |
| 359 | char *pbuf; | 373 | char *pbuf; |
| @@ -372,7 +386,12 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
| 372 | return -EINVAL; /* EOPNOTSUPP? */ | 386 | return -EINVAL; /* EOPNOTSUPP? */ |
| 373 | } | 387 | } |
| 374 | 388 | ||
| 375 | rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ, | 389 | tlink = cifs_sb_tlink(cifs_sb); |
| 390 | if (IS_ERR(tlink)) | ||
| 391 | return PTR_ERR(tlink); | ||
| 392 | tcon = tlink_tcon(tlink); | ||
| 393 | |||
| 394 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ, | ||
| 376 | CREATE_NOT_DIR, &netfid, &oplock, NULL, | 395 | CREATE_NOT_DIR, &netfid, &oplock, NULL, |
| 377 | cifs_sb->local_nls, | 396 | cifs_sb->local_nls, |
| 378 | cifs_sb->mnt_cifs_flags & | 397 | cifs_sb->mnt_cifs_flags & |
| @@ -380,7 +399,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
| 380 | if (rc == 0) { | 399 | if (rc == 0) { |
| 381 | int buf_type = CIFS_NO_BUFFER; | 400 | int buf_type = CIFS_NO_BUFFER; |
| 382 | /* Read header */ | 401 | /* Read header */ |
| 383 | rc = CIFSSMBRead(xid, pTcon, netfid, | 402 | rc = CIFSSMBRead(xid, tcon, netfid, |
| 384 | 24 /* length */, 0 /* offset */, | 403 | 24 /* length */, 0 /* offset */, |
| 385 | &bytes_read, &pbuf, &buf_type); | 404 | &bytes_read, &pbuf, &buf_type); |
| 386 | if ((rc == 0) && (bytes_read >= 8)) { | 405 | if ((rc == 0) && (bytes_read >= 8)) { |
| @@ -422,8 +441,9 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
| 422 | fattr->cf_dtype = DT_REG; | 441 | fattr->cf_dtype = DT_REG; |
| 423 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ | 442 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ |
| 424 | } | 443 | } |
| 425 | CIFSSMBClose(xid, pTcon, netfid); | 444 | CIFSSMBClose(xid, tcon, netfid); |
| 426 | } | 445 | } |
| 446 | cifs_put_tlink(tlink); | ||
| 427 | return rc; | 447 | return rc; |
| 428 | } | 448 | } |
| 429 | 449 | ||
| @@ -441,11 +461,19 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, | |||
| 441 | ssize_t rc; | 461 | ssize_t rc; |
| 442 | char ea_value[4]; | 462 | char ea_value[4]; |
| 443 | __u32 mode; | 463 | __u32 mode; |
| 464 | struct tcon_link *tlink; | ||
| 465 | struct cifsTconInfo *tcon; | ||
| 444 | 466 | ||
| 445 | rc = CIFSSMBQAllEAs(xid, cifs_sb->tcon, path, "SETFILEBITS", | 467 | tlink = cifs_sb_tlink(cifs_sb); |
| 468 | if (IS_ERR(tlink)) | ||
| 469 | return PTR_ERR(tlink); | ||
| 470 | tcon = tlink_tcon(tlink); | ||
| 471 | |||
| 472 | rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS", | ||
| 446 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, | 473 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, |
| 447 | cifs_sb->mnt_cifs_flags & | 474 | cifs_sb->mnt_cifs_flags & |
| 448 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 475 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 476 | cifs_put_tlink(tlink); | ||
| 449 | if (rc < 0) | 477 | if (rc < 0) |
| 450 | return (int)rc; | 478 | return (int)rc; |
| 451 | else if (rc > 3) { | 479 | else if (rc > 3) { |
| @@ -468,6 +496,8 @@ static void | |||
| 468 | cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, | 496 | cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, |
| 469 | struct cifs_sb_info *cifs_sb, bool adjust_tz) | 497 | struct cifs_sb_info *cifs_sb, bool adjust_tz) |
| 470 | { | 498 | { |
| 499 | struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); | ||
| 500 | |||
| 471 | memset(fattr, 0, sizeof(*fattr)); | 501 | memset(fattr, 0, sizeof(*fattr)); |
| 472 | fattr->cf_cifsattrs = le32_to_cpu(info->Attributes); | 502 | fattr->cf_cifsattrs = le32_to_cpu(info->Attributes); |
| 473 | if (info->DeletePending) | 503 | if (info->DeletePending) |
| @@ -482,8 +512,8 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, | |||
| 482 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); | 512 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); |
| 483 | 513 | ||
| 484 | if (adjust_tz) { | 514 | if (adjust_tz) { |
| 485 | fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj; | 515 | fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj; |
| 486 | fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj; | 516 | fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj; |
| 487 | } | 517 | } |
| 488 | 518 | ||
| 489 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); | 519 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); |
| @@ -515,8 +545,8 @@ int cifs_get_file_info(struct file *filp) | |||
| 515 | struct cifs_fattr fattr; | 545 | struct cifs_fattr fattr; |
| 516 | struct inode *inode = filp->f_path.dentry->d_inode; | 546 | struct inode *inode = filp->f_path.dentry->d_inode; |
| 517 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 547 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
| 518 | struct cifsTconInfo *tcon = cifs_sb->tcon; | ||
| 519 | struct cifsFileInfo *cfile = filp->private_data; | 548 | struct cifsFileInfo *cfile = filp->private_data; |
| 549 | struct cifsTconInfo *tcon = tlink_tcon(cfile->tlink); | ||
| 520 | 550 | ||
| 521 | xid = GetXid(); | 551 | xid = GetXid(); |
| 522 | rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); | 552 | rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); |
| @@ -554,26 +584,33 @@ int cifs_get_inode_info(struct inode **pinode, | |||
| 554 | { | 584 | { |
| 555 | int rc = 0, tmprc; | 585 | int rc = 0, tmprc; |
| 556 | struct cifsTconInfo *pTcon; | 586 | struct cifsTconInfo *pTcon; |
| 587 | struct tcon_link *tlink; | ||
| 557 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 588 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 558 | char *buf = NULL; | 589 | char *buf = NULL; |
| 559 | bool adjustTZ = false; | 590 | bool adjustTZ = false; |
| 560 | struct cifs_fattr fattr; | 591 | struct cifs_fattr fattr; |
| 561 | 592 | ||
| 562 | pTcon = cifs_sb->tcon; | 593 | tlink = cifs_sb_tlink(cifs_sb); |
| 594 | if (IS_ERR(tlink)) | ||
| 595 | return PTR_ERR(tlink); | ||
| 596 | pTcon = tlink_tcon(tlink); | ||
| 597 | |||
| 563 | cFYI(1, "Getting info on %s", full_path); | 598 | cFYI(1, "Getting info on %s", full_path); |
| 564 | 599 | ||
| 565 | if ((pfindData == NULL) && (*pinode != NULL)) { | 600 | if ((pfindData == NULL) && (*pinode != NULL)) { |
| 566 | if (CIFS_I(*pinode)->clientCanCacheRead) { | 601 | if (CIFS_I(*pinode)->clientCanCacheRead) { |
| 567 | cFYI(1, "No need to revalidate cached inode sizes"); | 602 | cFYI(1, "No need to revalidate cached inode sizes"); |
| 568 | return rc; | 603 | goto cgii_exit; |
| 569 | } | 604 | } |
| 570 | } | 605 | } |
| 571 | 606 | ||
| 572 | /* if file info not passed in then get it from server */ | 607 | /* if file info not passed in then get it from server */ |
| 573 | if (pfindData == NULL) { | 608 | if (pfindData == NULL) { |
| 574 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | 609 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
| 575 | if (buf == NULL) | 610 | if (buf == NULL) { |
| 576 | return -ENOMEM; | 611 | rc = -ENOMEM; |
| 612 | goto cgii_exit; | ||
| 613 | } | ||
| 577 | pfindData = (FILE_ALL_INFO *)buf; | 614 | pfindData = (FILE_ALL_INFO *)buf; |
| 578 | 615 | ||
| 579 | /* could do find first instead but this returns more info */ | 616 | /* could do find first instead but this returns more info */ |
| @@ -661,6 +698,13 @@ int cifs_get_inode_info(struct inode **pinode, | |||
| 661 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) | 698 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) |
| 662 | cifs_sfu_mode(&fattr, full_path, cifs_sb, xid); | 699 | cifs_sfu_mode(&fattr, full_path, cifs_sb, xid); |
| 663 | 700 | ||
| 701 | /* check for Minshall+French symlinks */ | ||
| 702 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { | ||
| 703 | tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid); | ||
| 704 | if (tmprc) | ||
| 705 | cFYI(1, "CIFSCheckMFSymlink: %d", tmprc); | ||
| 706 | } | ||
| 707 | |||
| 664 | if (!*pinode) { | 708 | if (!*pinode) { |
| 665 | *pinode = cifs_iget(sb, &fattr); | 709 | *pinode = cifs_iget(sb, &fattr); |
| 666 | if (!*pinode) | 710 | if (!*pinode) |
| @@ -671,6 +715,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
| 671 | 715 | ||
| 672 | cgii_exit: | 716 | cgii_exit: |
| 673 | kfree(buf); | 717 | kfree(buf); |
| 718 | cifs_put_tlink(tlink); | ||
| 674 | return rc; | 719 | return rc; |
| 675 | } | 720 | } |
| 676 | 721 | ||
| @@ -683,6 +728,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) | |||
| 683 | int pplen = cifs_sb->prepathlen; | 728 | int pplen = cifs_sb->prepathlen; |
| 684 | int dfsplen; | 729 | int dfsplen; |
| 685 | char *full_path = NULL; | 730 | char *full_path = NULL; |
| 731 | struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); | ||
| 686 | 732 | ||
| 687 | /* if no prefix path, simply set path to the root of share to "" */ | 733 | /* if no prefix path, simply set path to the root of share to "" */ |
| 688 | if (pplen == 0) { | 734 | if (pplen == 0) { |
| @@ -692,8 +738,8 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) | |||
| 692 | return full_path; | 738 | return full_path; |
| 693 | } | 739 | } |
| 694 | 740 | ||
| 695 | if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS)) | 741 | if (tcon->Flags & SMB_SHARE_IS_IN_DFS) |
| 696 | dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1); | 742 | dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1); |
| 697 | else | 743 | else |
| 698 | dfsplen = 0; | 744 | dfsplen = 0; |
| 699 | 745 | ||
| @@ -702,7 +748,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) | |||
| 702 | return full_path; | 748 | return full_path; |
| 703 | 749 | ||
| 704 | if (dfsplen) { | 750 | if (dfsplen) { |
| 705 | strncpy(full_path, cifs_sb->tcon->treeName, dfsplen); | 751 | strncpy(full_path, tcon->treeName, dfsplen); |
| 706 | /* switch slash direction in prepath depending on whether | 752 | /* switch slash direction in prepath depending on whether |
| 707 | * windows or posix style path names | 753 | * windows or posix style path names |
| 708 | */ | 754 | */ |
| @@ -818,18 +864,18 @@ retry_iget5_locked: | |||
| 818 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | 864 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) |
| 819 | { | 865 | { |
| 820 | int xid; | 866 | int xid; |
| 821 | struct cifs_sb_info *cifs_sb; | 867 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 822 | struct inode *inode = NULL; | 868 | struct inode *inode = NULL; |
| 823 | long rc; | 869 | long rc; |
| 824 | char *full_path; | 870 | char *full_path; |
| 871 | struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); | ||
| 825 | 872 | ||
| 826 | cifs_sb = CIFS_SB(sb); | ||
| 827 | full_path = cifs_build_path_to_root(cifs_sb); | 873 | full_path = cifs_build_path_to_root(cifs_sb); |
| 828 | if (full_path == NULL) | 874 | if (full_path == NULL) |
| 829 | return ERR_PTR(-ENOMEM); | 875 | return ERR_PTR(-ENOMEM); |
| 830 | 876 | ||
| 831 | xid = GetXid(); | 877 | xid = GetXid(); |
| 832 | if (cifs_sb->tcon->unix_ext) | 878 | if (tcon->unix_ext) |
| 833 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); | 879 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); |
| 834 | else | 880 | else |
| 835 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, | 881 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, |
| @@ -840,10 +886,10 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
| 840 | 886 | ||
| 841 | #ifdef CONFIG_CIFS_FSCACHE | 887 | #ifdef CONFIG_CIFS_FSCACHE |
| 842 | /* populate tcon->resource_id */ | 888 | /* populate tcon->resource_id */ |
| 843 | cifs_sb->tcon->resource_id = CIFS_I(inode)->uniqueid; | 889 | tcon->resource_id = CIFS_I(inode)->uniqueid; |
| 844 | #endif | 890 | #endif |
| 845 | 891 | ||
| 846 | if (rc && cifs_sb->tcon->ipc) { | 892 | if (rc && tcon->ipc) { |
| 847 | cFYI(1, "ipc connection - fake read inode"); | 893 | cFYI(1, "ipc connection - fake read inode"); |
| 848 | inode->i_mode |= S_IFDIR; | 894 | inode->i_mode |= S_IFDIR; |
| 849 | inode->i_nlink = 2; | 895 | inode->i_nlink = 2; |
| @@ -879,7 +925,8 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, | |||
| 879 | struct cifsFileInfo *open_file; | 925 | struct cifsFileInfo *open_file; |
| 880 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 926 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
| 881 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 927 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
| 882 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 928 | struct tcon_link *tlink = NULL; |
| 929 | struct cifsTconInfo *pTcon; | ||
| 883 | FILE_BASIC_INFO info_buf; | 930 | FILE_BASIC_INFO info_buf; |
| 884 | 931 | ||
| 885 | if (attrs == NULL) | 932 | if (attrs == NULL) |
| @@ -918,13 +965,22 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, | |||
| 918 | /* | 965 | /* |
| 919 | * If the file is already open for write, just use that fileid | 966 | * If the file is already open for write, just use that fileid |
| 920 | */ | 967 | */ |
| 921 | open_file = find_writable_file(cifsInode); | 968 | open_file = find_writable_file(cifsInode, true); |
| 922 | if (open_file) { | 969 | if (open_file) { |
| 923 | netfid = open_file->netfid; | 970 | netfid = open_file->netfid; |
| 924 | netpid = open_file->pid; | 971 | netpid = open_file->pid; |
| 972 | pTcon = tlink_tcon(open_file->tlink); | ||
| 925 | goto set_via_filehandle; | 973 | goto set_via_filehandle; |
| 926 | } | 974 | } |
| 927 | 975 | ||
| 976 | tlink = cifs_sb_tlink(cifs_sb); | ||
| 977 | if (IS_ERR(tlink)) { | ||
| 978 | rc = PTR_ERR(tlink); | ||
| 979 | tlink = NULL; | ||
| 980 | goto out; | ||
| 981 | } | ||
| 982 | pTcon = tlink_tcon(tlink); | ||
| 983 | |||
| 928 | /* | 984 | /* |
| 929 | * NT4 apparently returns success on this call, but it doesn't | 985 | * NT4 apparently returns success on this call, but it doesn't |
| 930 | * really work. | 986 | * really work. |
| @@ -968,6 +1024,8 @@ set_via_filehandle: | |||
| 968 | else | 1024 | else |
| 969 | cifsFileInfo_put(open_file); | 1025 | cifsFileInfo_put(open_file); |
| 970 | out: | 1026 | out: |
| 1027 | if (tlink != NULL) | ||
| 1028 | cifs_put_tlink(tlink); | ||
| 971 | return rc; | 1029 | return rc; |
| 972 | } | 1030 | } |
| 973 | 1031 | ||
| @@ -985,10 +1043,16 @@ cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid) | |||
| 985 | struct inode *inode = dentry->d_inode; | 1043 | struct inode *inode = dentry->d_inode; |
| 986 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1044 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
| 987 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1045 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
| 988 | struct cifsTconInfo *tcon = cifs_sb->tcon; | 1046 | struct tcon_link *tlink; |
| 1047 | struct cifsTconInfo *tcon; | ||
| 989 | __u32 dosattr, origattr; | 1048 | __u32 dosattr, origattr; |
| 990 | FILE_BASIC_INFO *info_buf = NULL; | 1049 | FILE_BASIC_INFO *info_buf = NULL; |
| 991 | 1050 | ||
| 1051 | tlink = cifs_sb_tlink(cifs_sb); | ||
| 1052 | if (IS_ERR(tlink)) | ||
| 1053 | return PTR_ERR(tlink); | ||
| 1054 | tcon = tlink_tcon(tlink); | ||
| 1055 | |||
| 992 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, | 1056 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, |
| 993 | DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, | 1057 | DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, |
| 994 | &netfid, &oplock, NULL, cifs_sb->local_nls, | 1058 | &netfid, &oplock, NULL, cifs_sb->local_nls, |
| @@ -1057,6 +1121,7 @@ out_close: | |||
| 1057 | CIFSSMBClose(xid, tcon, netfid); | 1121 | CIFSSMBClose(xid, tcon, netfid); |
| 1058 | out: | 1122 | out: |
| 1059 | kfree(info_buf); | 1123 | kfree(info_buf); |
| 1124 | cifs_put_tlink(tlink); | ||
| 1060 | return rc; | 1125 | return rc; |
| 1061 | 1126 | ||
| 1062 | /* | 1127 | /* |
| @@ -1096,12 +1161,18 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 1096 | struct cifsInodeInfo *cifs_inode; | 1161 | struct cifsInodeInfo *cifs_inode; |
| 1097 | struct super_block *sb = dir->i_sb; | 1162 | struct super_block *sb = dir->i_sb; |
| 1098 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 1163 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 1099 | struct cifsTconInfo *tcon = cifs_sb->tcon; | 1164 | struct tcon_link *tlink; |
| 1165 | struct cifsTconInfo *tcon; | ||
| 1100 | struct iattr *attrs = NULL; | 1166 | struct iattr *attrs = NULL; |
| 1101 | __u32 dosattr = 0, origattr = 0; | 1167 | __u32 dosattr = 0, origattr = 0; |
| 1102 | 1168 | ||
| 1103 | cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry); | 1169 | cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry); |
| 1104 | 1170 | ||
| 1171 | tlink = cifs_sb_tlink(cifs_sb); | ||
| 1172 | if (IS_ERR(tlink)) | ||
| 1173 | return PTR_ERR(tlink); | ||
| 1174 | tcon = tlink_tcon(tlink); | ||
| 1175 | |||
| 1105 | xid = GetXid(); | 1176 | xid = GetXid(); |
| 1106 | 1177 | ||
| 1107 | /* Unlink can be called from rename so we can not take the | 1178 | /* Unlink can be called from rename so we can not take the |
| @@ -1109,8 +1180,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 1109 | full_path = build_path_from_dentry(dentry); | 1180 | full_path = build_path_from_dentry(dentry); |
| 1110 | if (full_path == NULL) { | 1181 | if (full_path == NULL) { |
| 1111 | rc = -ENOMEM; | 1182 | rc = -ENOMEM; |
| 1112 | FreeXid(xid); | 1183 | goto unlink_out; |
| 1113 | return rc; | ||
| 1114 | } | 1184 | } |
| 1115 | 1185 | ||
| 1116 | if ((tcon->ses->capabilities & CAP_UNIX) && | 1186 | if ((tcon->ses->capabilities & CAP_UNIX) && |
| @@ -1176,10 +1246,11 @@ out_reval: | |||
| 1176 | dir->i_ctime = dir->i_mtime = current_fs_time(sb); | 1246 | dir->i_ctime = dir->i_mtime = current_fs_time(sb); |
| 1177 | cifs_inode = CIFS_I(dir); | 1247 | cifs_inode = CIFS_I(dir); |
| 1178 | CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ | 1248 | CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ |
| 1179 | 1249 | unlink_out: | |
| 1180 | kfree(full_path); | 1250 | kfree(full_path); |
| 1181 | kfree(attrs); | 1251 | kfree(attrs); |
| 1182 | FreeXid(xid); | 1252 | FreeXid(xid); |
| 1253 | cifs_put_tlink(tlink); | ||
| 1183 | return rc; | 1254 | return rc; |
| 1184 | } | 1255 | } |
| 1185 | 1256 | ||
| @@ -1188,6 +1259,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
| 1188 | int rc = 0, tmprc; | 1259 | int rc = 0, tmprc; |
| 1189 | int xid; | 1260 | int xid; |
| 1190 | struct cifs_sb_info *cifs_sb; | 1261 | struct cifs_sb_info *cifs_sb; |
| 1262 | struct tcon_link *tlink; | ||
| 1191 | struct cifsTconInfo *pTcon; | 1263 | struct cifsTconInfo *pTcon; |
| 1192 | char *full_path = NULL; | 1264 | char *full_path = NULL; |
| 1193 | struct inode *newinode = NULL; | 1265 | struct inode *newinode = NULL; |
| @@ -1195,16 +1267,18 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
| 1195 | 1267 | ||
| 1196 | cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode); | 1268 | cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode); |
| 1197 | 1269 | ||
| 1198 | xid = GetXid(); | ||
| 1199 | |||
| 1200 | cifs_sb = CIFS_SB(inode->i_sb); | 1270 | cifs_sb = CIFS_SB(inode->i_sb); |
| 1201 | pTcon = cifs_sb->tcon; | 1271 | tlink = cifs_sb_tlink(cifs_sb); |
| 1272 | if (IS_ERR(tlink)) | ||
| 1273 | return PTR_ERR(tlink); | ||
| 1274 | pTcon = tlink_tcon(tlink); | ||
| 1275 | |||
| 1276 | xid = GetXid(); | ||
| 1202 | 1277 | ||
| 1203 | full_path = build_path_from_dentry(direntry); | 1278 | full_path = build_path_from_dentry(direntry); |
| 1204 | if (full_path == NULL) { | 1279 | if (full_path == NULL) { |
| 1205 | rc = -ENOMEM; | 1280 | rc = -ENOMEM; |
| 1206 | FreeXid(xid); | 1281 | goto mkdir_out; |
| 1207 | return rc; | ||
| 1208 | } | 1282 | } |
| 1209 | 1283 | ||
| 1210 | if ((pTcon->ses->capabilities & CAP_UNIX) && | 1284 | if ((pTcon->ses->capabilities & CAP_UNIX) && |
| @@ -1362,6 +1436,7 @@ mkdir_get_info: | |||
| 1362 | mkdir_out: | 1436 | mkdir_out: |
| 1363 | kfree(full_path); | 1437 | kfree(full_path); |
| 1364 | FreeXid(xid); | 1438 | FreeXid(xid); |
| 1439 | cifs_put_tlink(tlink); | ||
| 1365 | return rc; | 1440 | return rc; |
| 1366 | } | 1441 | } |
| 1367 | 1442 | ||
| @@ -1370,6 +1445,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
| 1370 | int rc = 0; | 1445 | int rc = 0; |
| 1371 | int xid; | 1446 | int xid; |
| 1372 | struct cifs_sb_info *cifs_sb; | 1447 | struct cifs_sb_info *cifs_sb; |
| 1448 | struct tcon_link *tlink; | ||
| 1373 | struct cifsTconInfo *pTcon; | 1449 | struct cifsTconInfo *pTcon; |
| 1374 | char *full_path = NULL; | 1450 | char *full_path = NULL; |
| 1375 | struct cifsInodeInfo *cifsInode; | 1451 | struct cifsInodeInfo *cifsInode; |
| @@ -1378,18 +1454,23 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
| 1378 | 1454 | ||
| 1379 | xid = GetXid(); | 1455 | xid = GetXid(); |
| 1380 | 1456 | ||
| 1381 | cifs_sb = CIFS_SB(inode->i_sb); | ||
| 1382 | pTcon = cifs_sb->tcon; | ||
| 1383 | |||
| 1384 | full_path = build_path_from_dentry(direntry); | 1457 | full_path = build_path_from_dentry(direntry); |
| 1385 | if (full_path == NULL) { | 1458 | if (full_path == NULL) { |
| 1386 | rc = -ENOMEM; | 1459 | rc = -ENOMEM; |
| 1387 | FreeXid(xid); | 1460 | goto rmdir_exit; |
| 1388 | return rc; | ||
| 1389 | } | 1461 | } |
| 1390 | 1462 | ||
| 1463 | cifs_sb = CIFS_SB(inode->i_sb); | ||
| 1464 | tlink = cifs_sb_tlink(cifs_sb); | ||
| 1465 | if (IS_ERR(tlink)) { | ||
| 1466 | rc = PTR_ERR(tlink); | ||
| 1467 | goto rmdir_exit; | ||
| 1468 | } | ||
| 1469 | pTcon = tlink_tcon(tlink); | ||
| 1470 | |||
| 1391 | rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, | 1471 | rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, |
| 1392 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 1472 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 1473 | cifs_put_tlink(tlink); | ||
| 1393 | 1474 | ||
| 1394 | if (!rc) { | 1475 | if (!rc) { |
| 1395 | drop_nlink(inode); | 1476 | drop_nlink(inode); |
| @@ -1410,6 +1491,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
| 1410 | direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = | 1491 | direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = |
| 1411 | current_fs_time(inode->i_sb); | 1492 | current_fs_time(inode->i_sb); |
| 1412 | 1493 | ||
| 1494 | rmdir_exit: | ||
| 1413 | kfree(full_path); | 1495 | kfree(full_path); |
| 1414 | FreeXid(xid); | 1496 | FreeXid(xid); |
| 1415 | return rc; | 1497 | return rc; |
| @@ -1420,10 +1502,16 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, | |||
| 1420 | struct dentry *to_dentry, const char *toPath) | 1502 | struct dentry *to_dentry, const char *toPath) |
| 1421 | { | 1503 | { |
| 1422 | struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb); | 1504 | struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb); |
| 1423 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 1505 | struct tcon_link *tlink; |
| 1506 | struct cifsTconInfo *pTcon; | ||
| 1424 | __u16 srcfid; | 1507 | __u16 srcfid; |
| 1425 | int oplock, rc; | 1508 | int oplock, rc; |
| 1426 | 1509 | ||
| 1510 | tlink = cifs_sb_tlink(cifs_sb); | ||
| 1511 | if (IS_ERR(tlink)) | ||
| 1512 | return PTR_ERR(tlink); | ||
| 1513 | pTcon = tlink_tcon(tlink); | ||
| 1514 | |||
| 1427 | /* try path-based rename first */ | 1515 | /* try path-based rename first */ |
| 1428 | rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls, | 1516 | rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls, |
| 1429 | cifs_sb->mnt_cifs_flags & | 1517 | cifs_sb->mnt_cifs_flags & |
| @@ -1435,11 +1523,11 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, | |||
| 1435 | * rename by filehandle to various Windows servers. | 1523 | * rename by filehandle to various Windows servers. |
| 1436 | */ | 1524 | */ |
| 1437 | if (rc == 0 || rc != -ETXTBSY) | 1525 | if (rc == 0 || rc != -ETXTBSY) |
| 1438 | return rc; | 1526 | goto do_rename_exit; |
| 1439 | 1527 | ||
| 1440 | /* open-file renames don't work across directories */ | 1528 | /* open-file renames don't work across directories */ |
| 1441 | if (to_dentry->d_parent != from_dentry->d_parent) | 1529 | if (to_dentry->d_parent != from_dentry->d_parent) |
| 1442 | return rc; | 1530 | goto do_rename_exit; |
| 1443 | 1531 | ||
| 1444 | /* open the file to be renamed -- we need DELETE perms */ | 1532 | /* open the file to be renamed -- we need DELETE perms */ |
| 1445 | rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, | 1533 | rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, |
| @@ -1455,7 +1543,8 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, | |||
| 1455 | 1543 | ||
| 1456 | CIFSSMBClose(xid, pTcon, srcfid); | 1544 | CIFSSMBClose(xid, pTcon, srcfid); |
| 1457 | } | 1545 | } |
| 1458 | 1546 | do_rename_exit: | |
| 1547 | cifs_put_tlink(tlink); | ||
| 1459 | return rc; | 1548 | return rc; |
| 1460 | } | 1549 | } |
| 1461 | 1550 | ||
| @@ -1465,13 +1554,17 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
| 1465 | char *fromName = NULL; | 1554 | char *fromName = NULL; |
| 1466 | char *toName = NULL; | 1555 | char *toName = NULL; |
| 1467 | struct cifs_sb_info *cifs_sb; | 1556 | struct cifs_sb_info *cifs_sb; |
| 1557 | struct tcon_link *tlink; | ||
| 1468 | struct cifsTconInfo *tcon; | 1558 | struct cifsTconInfo *tcon; |
| 1469 | FILE_UNIX_BASIC_INFO *info_buf_source = NULL; | 1559 | FILE_UNIX_BASIC_INFO *info_buf_source = NULL; |
| 1470 | FILE_UNIX_BASIC_INFO *info_buf_target; | 1560 | FILE_UNIX_BASIC_INFO *info_buf_target; |
| 1471 | int xid, rc, tmprc; | 1561 | int xid, rc, tmprc; |
| 1472 | 1562 | ||
| 1473 | cifs_sb = CIFS_SB(source_dir->i_sb); | 1563 | cifs_sb = CIFS_SB(source_dir->i_sb); |
| 1474 | tcon = cifs_sb->tcon; | 1564 | tlink = cifs_sb_tlink(cifs_sb); |
| 1565 | if (IS_ERR(tlink)) | ||
| 1566 | return PTR_ERR(tlink); | ||
| 1567 | tcon = tlink_tcon(tlink); | ||
| 1475 | 1568 | ||
| 1476 | xid = GetXid(); | 1569 | xid = GetXid(); |
| 1477 | 1570 | ||
| @@ -1547,6 +1640,7 @@ cifs_rename_exit: | |||
| 1547 | kfree(fromName); | 1640 | kfree(fromName); |
| 1548 | kfree(toName); | 1641 | kfree(toName); |
| 1549 | FreeXid(xid); | 1642 | FreeXid(xid); |
| 1643 | cifs_put_tlink(tlink); | ||
| 1550 | return rc; | 1644 | return rc; |
| 1551 | } | 1645 | } |
| 1552 | 1646 | ||
| @@ -1599,11 +1693,12 @@ int cifs_revalidate_file(struct file *filp) | |||
| 1599 | { | 1693 | { |
| 1600 | int rc = 0; | 1694 | int rc = 0; |
| 1601 | struct inode *inode = filp->f_path.dentry->d_inode; | 1695 | struct inode *inode = filp->f_path.dentry->d_inode; |
| 1696 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; | ||
| 1602 | 1697 | ||
| 1603 | if (!cifs_inode_needs_reval(inode)) | 1698 | if (!cifs_inode_needs_reval(inode)) |
| 1604 | goto check_inval; | 1699 | goto check_inval; |
| 1605 | 1700 | ||
| 1606 | if (CIFS_SB(inode->i_sb)->tcon->unix_ext) | 1701 | if (tlink_tcon(cfile->tlink)->unix_ext) |
| 1607 | rc = cifs_get_file_info_unix(filp); | 1702 | rc = cifs_get_file_info_unix(filp); |
| 1608 | else | 1703 | else |
| 1609 | rc = cifs_get_file_info(filp); | 1704 | rc = cifs_get_file_info(filp); |
| @@ -1644,7 +1739,7 @@ int cifs_revalidate_dentry(struct dentry *dentry) | |||
| 1644 | "jiffies %ld", full_path, inode, inode->i_count.counter, | 1739 | "jiffies %ld", full_path, inode, inode->i_count.counter, |
| 1645 | dentry, dentry->d_time, jiffies); | 1740 | dentry, dentry->d_time, jiffies); |
| 1646 | 1741 | ||
| 1647 | if (CIFS_SB(sb)->tcon->unix_ext) | 1742 | if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) |
| 1648 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); | 1743 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); |
| 1649 | else | 1744 | else |
| 1650 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, | 1745 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, |
| @@ -1660,13 +1755,29 @@ check_inval: | |||
| 1660 | } | 1755 | } |
| 1661 | 1756 | ||
| 1662 | int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, | 1757 | int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, |
| 1663 | struct kstat *stat) | 1758 | struct kstat *stat) |
| 1664 | { | 1759 | { |
| 1760 | struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); | ||
| 1761 | struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); | ||
| 1665 | int err = cifs_revalidate_dentry(dentry); | 1762 | int err = cifs_revalidate_dentry(dentry); |
| 1763 | |||
| 1666 | if (!err) { | 1764 | if (!err) { |
| 1667 | generic_fillattr(dentry->d_inode, stat); | 1765 | generic_fillattr(dentry->d_inode, stat); |
| 1668 | stat->blksize = CIFS_MAX_MSGSIZE; | 1766 | stat->blksize = CIFS_MAX_MSGSIZE; |
| 1669 | stat->ino = CIFS_I(dentry->d_inode)->uniqueid; | 1767 | stat->ino = CIFS_I(dentry->d_inode)->uniqueid; |
| 1768 | |||
| 1769 | /* | ||
| 1770 | * If on a multiuser mount without unix extensions, and the | ||
| 1771 | * admin hasn't overridden them, set the ownership to the | ||
| 1772 | * fsuid/fsgid of the current process. | ||
| 1773 | */ | ||
| 1774 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) && | ||
| 1775 | !tcon->unix_ext) { | ||
| 1776 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) | ||
| 1777 | stat->uid = current_fsuid(); | ||
| 1778 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) | ||
| 1779 | stat->gid = current_fsgid(); | ||
| 1780 | } | ||
| 1670 | } | 1781 | } |
| 1671 | return err; | 1782 | return err; |
| 1672 | } | 1783 | } |
| @@ -1708,7 +1819,8 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
| 1708 | struct cifsFileInfo *open_file; | 1819 | struct cifsFileInfo *open_file; |
| 1709 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1820 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
| 1710 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1821 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
| 1711 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 1822 | struct tcon_link *tlink = NULL; |
| 1823 | struct cifsTconInfo *pTcon = NULL; | ||
| 1712 | 1824 | ||
| 1713 | /* | 1825 | /* |
| 1714 | * To avoid spurious oplock breaks from server, in the case of | 1826 | * To avoid spurious oplock breaks from server, in the case of |
| @@ -1719,10 +1831,11 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
| 1719 | * writebehind data than the SMB timeout for the SetPathInfo | 1831 | * writebehind data than the SMB timeout for the SetPathInfo |
| 1720 | * request would allow | 1832 | * request would allow |
| 1721 | */ | 1833 | */ |
| 1722 | open_file = find_writable_file(cifsInode); | 1834 | open_file = find_writable_file(cifsInode, true); |
| 1723 | if (open_file) { | 1835 | if (open_file) { |
| 1724 | __u16 nfid = open_file->netfid; | 1836 | __u16 nfid = open_file->netfid; |
| 1725 | __u32 npid = open_file->pid; | 1837 | __u32 npid = open_file->pid; |
| 1838 | pTcon = tlink_tcon(open_file->tlink); | ||
| 1726 | rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid, | 1839 | rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid, |
| 1727 | npid, false); | 1840 | npid, false); |
| 1728 | cifsFileInfo_put(open_file); | 1841 | cifsFileInfo_put(open_file); |
| @@ -1737,6 +1850,13 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
| 1737 | rc = -EINVAL; | 1850 | rc = -EINVAL; |
| 1738 | 1851 | ||
| 1739 | if (rc != 0) { | 1852 | if (rc != 0) { |
| 1853 | if (pTcon == NULL) { | ||
| 1854 | tlink = cifs_sb_tlink(cifs_sb); | ||
| 1855 | if (IS_ERR(tlink)) | ||
| 1856 | return PTR_ERR(tlink); | ||
| 1857 | pTcon = tlink_tcon(tlink); | ||
| 1858 | } | ||
| 1859 | |||
| 1740 | /* Set file size by pathname rather than by handle | 1860 | /* Set file size by pathname rather than by handle |
| 1741 | either because no valid, writeable file handle for | 1861 | either because no valid, writeable file handle for |
| 1742 | it was found or because there was an error setting | 1862 | it was found or because there was an error setting |
| @@ -1766,6 +1886,8 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
| 1766 | CIFSSMBClose(xid, pTcon, netfid); | 1886 | CIFSSMBClose(xid, pTcon, netfid); |
| 1767 | } | 1887 | } |
| 1768 | } | 1888 | } |
| 1889 | if (tlink) | ||
| 1890 | cifs_put_tlink(tlink); | ||
| 1769 | } | 1891 | } |
| 1770 | 1892 | ||
| 1771 | if (rc == 0) { | 1893 | if (rc == 0) { |
| @@ -1786,7 +1908,8 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
| 1786 | struct inode *inode = direntry->d_inode; | 1908 | struct inode *inode = direntry->d_inode; |
| 1787 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1909 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
| 1788 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1910 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
| 1789 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 1911 | struct tcon_link *tlink; |
| 1912 | struct cifsTconInfo *pTcon; | ||
| 1790 | struct cifs_unix_set_info_args *args = NULL; | 1913 | struct cifs_unix_set_info_args *args = NULL; |
| 1791 | struct cifsFileInfo *open_file; | 1914 | struct cifsFileInfo *open_file; |
| 1792 | 1915 | ||
| @@ -1873,17 +1996,25 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
| 1873 | args->ctime = NO_CHANGE_64; | 1996 | args->ctime = NO_CHANGE_64; |
| 1874 | 1997 | ||
| 1875 | args->device = 0; | 1998 | args->device = 0; |
| 1876 | open_file = find_writable_file(cifsInode); | 1999 | open_file = find_writable_file(cifsInode, true); |
| 1877 | if (open_file) { | 2000 | if (open_file) { |
| 1878 | u16 nfid = open_file->netfid; | 2001 | u16 nfid = open_file->netfid; |
| 1879 | u32 npid = open_file->pid; | 2002 | u32 npid = open_file->pid; |
| 2003 | pTcon = tlink_tcon(open_file->tlink); | ||
| 1880 | rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); | 2004 | rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); |
| 1881 | cifsFileInfo_put(open_file); | 2005 | cifsFileInfo_put(open_file); |
| 1882 | } else { | 2006 | } else { |
| 2007 | tlink = cifs_sb_tlink(cifs_sb); | ||
| 2008 | if (IS_ERR(tlink)) { | ||
| 2009 | rc = PTR_ERR(tlink); | ||
| 2010 | goto out; | ||
| 2011 | } | ||
| 2012 | pTcon = tlink_tcon(tlink); | ||
| 1883 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, | 2013 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, |
| 1884 | cifs_sb->local_nls, | 2014 | cifs_sb->local_nls, |
| 1885 | cifs_sb->mnt_cifs_flags & | 2015 | cifs_sb->mnt_cifs_flags & |
| 1886 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 2016 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 2017 | cifs_put_tlink(tlink); | ||
| 1887 | } | 2018 | } |
| 1888 | 2019 | ||
| 1889 | if (rc) | 2020 | if (rc) |
| @@ -2064,7 +2195,7 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
| 2064 | { | 2195 | { |
| 2065 | struct inode *inode = direntry->d_inode; | 2196 | struct inode *inode = direntry->d_inode; |
| 2066 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 2197 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
| 2067 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 2198 | struct cifsTconInfo *pTcon = cifs_sb_master_tcon(cifs_sb); |
| 2068 | 2199 | ||
| 2069 | if (pTcon->unix_ext) | 2200 | if (pTcon->unix_ext) |
| 2070 | return cifs_setattr_unix(direntry, attrs); | 2201 | return cifs_setattr_unix(direntry, attrs); |
