diff options
author | Ingo Molnar <mingo@elte.hu> | 2010-10-30 04:43:08 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-10-30 04:43:08 -0400 |
commit | 169ed55bd30305b933f52bfab32a58671d44ab68 (patch) | |
tree | 32e280957474f458901abfce16fa2a1687ef7497 /fs/cifs/inode.c | |
parent | 3d7851b3cdd43a734e5cc4c643fd886ab28ad4d5 (diff) | |
parent | 45f81b1c96d9793e47ce925d257ea693ce0b193e (diff) |
Merge branch 'tip/perf/jump-label-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace into perf/urgent
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); |