diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 221 |
1 files changed, 136 insertions, 85 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 8852470b4fbb..9b018c8334fa 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -295,7 +295,7 @@ int cifs_get_file_info_unix(struct file *filp) | |||
295 | struct inode *inode = filp->f_path.dentry->d_inode; | 295 | struct inode *inode = filp->f_path.dentry->d_inode; |
296 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 296 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
297 | struct cifsFileInfo *cfile = filp->private_data; | 297 | struct cifsFileInfo *cfile = filp->private_data; |
298 | struct cifsTconInfo *tcon = tlink_tcon(cfile->tlink); | 298 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
299 | 299 | ||
300 | xid = GetXid(); | 300 | xid = GetXid(); |
301 | rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); | 301 | rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); |
@@ -318,7 +318,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
318 | int rc; | 318 | int rc; |
319 | FILE_UNIX_BASIC_INFO find_data; | 319 | FILE_UNIX_BASIC_INFO find_data; |
320 | struct cifs_fattr fattr; | 320 | struct cifs_fattr fattr; |
321 | struct cifsTconInfo *tcon; | 321 | struct cifs_tcon *tcon; |
322 | struct tcon_link *tlink; | 322 | struct tcon_link *tlink; |
323 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 323 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
324 | 324 | ||
@@ -373,7 +373,8 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
373 | int oplock = 0; | 373 | int oplock = 0; |
374 | __u16 netfid; | 374 | __u16 netfid; |
375 | struct tcon_link *tlink; | 375 | struct tcon_link *tlink; |
376 | struct cifsTconInfo *tcon; | 376 | struct cifs_tcon *tcon; |
377 | struct cifs_io_parms io_parms; | ||
377 | char buf[24]; | 378 | char buf[24]; |
378 | unsigned int bytes_read; | 379 | unsigned int bytes_read; |
379 | char *pbuf; | 380 | char *pbuf; |
@@ -405,9 +406,13 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
405 | if (rc == 0) { | 406 | if (rc == 0) { |
406 | int buf_type = CIFS_NO_BUFFER; | 407 | int buf_type = CIFS_NO_BUFFER; |
407 | /* Read header */ | 408 | /* Read header */ |
408 | rc = CIFSSMBRead(xid, tcon, netfid, | 409 | io_parms.netfid = netfid; |
409 | 24 /* length */, 0 /* offset */, | 410 | io_parms.pid = current->tgid; |
410 | &bytes_read, &pbuf, &buf_type); | 411 | io_parms.tcon = tcon; |
412 | io_parms.offset = 0; | ||
413 | io_parms.length = 24; | ||
414 | rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, | ||
415 | &buf_type); | ||
411 | if ((rc == 0) && (bytes_read >= 8)) { | 416 | if ((rc == 0) && (bytes_read >= 8)) { |
412 | if (memcmp("IntxBLK", pbuf, 8) == 0) { | 417 | if (memcmp("IntxBLK", pbuf, 8) == 0) { |
413 | cFYI(1, "Block device"); | 418 | cFYI(1, "Block device"); |
@@ -468,7 +473,7 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, | |||
468 | char ea_value[4]; | 473 | char ea_value[4]; |
469 | __u32 mode; | 474 | __u32 mode; |
470 | struct tcon_link *tlink; | 475 | struct tcon_link *tlink; |
471 | struct cifsTconInfo *tcon; | 476 | struct cifs_tcon *tcon; |
472 | 477 | ||
473 | tlink = cifs_sb_tlink(cifs_sb); | 478 | tlink = cifs_sb_tlink(cifs_sb); |
474 | if (IS_ERR(tlink)) | 479 | if (IS_ERR(tlink)) |
@@ -502,7 +507,7 @@ static void | |||
502 | cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, | 507 | cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, |
503 | struct cifs_sb_info *cifs_sb, bool adjust_tz) | 508 | struct cifs_sb_info *cifs_sb, bool adjust_tz) |
504 | { | 509 | { |
505 | struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); | 510 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); |
506 | 511 | ||
507 | memset(fattr, 0, sizeof(*fattr)); | 512 | memset(fattr, 0, sizeof(*fattr)); |
508 | fattr->cf_cifsattrs = le32_to_cpu(info->Attributes); | 513 | fattr->cf_cifsattrs = le32_to_cpu(info->Attributes); |
@@ -553,7 +558,7 @@ int cifs_get_file_info(struct file *filp) | |||
553 | struct inode *inode = filp->f_path.dentry->d_inode; | 558 | struct inode *inode = filp->f_path.dentry->d_inode; |
554 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 559 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
555 | struct cifsFileInfo *cfile = filp->private_data; | 560 | struct cifsFileInfo *cfile = filp->private_data; |
556 | struct cifsTconInfo *tcon = tlink_tcon(cfile->tlink); | 561 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
557 | 562 | ||
558 | xid = GetXid(); | 563 | xid = GetXid(); |
559 | rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); | 564 | rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); |
@@ -590,7 +595,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
590 | struct super_block *sb, int xid, const __u16 *pfid) | 595 | struct super_block *sb, int xid, const __u16 *pfid) |
591 | { | 596 | { |
592 | int rc = 0, tmprc; | 597 | int rc = 0, tmprc; |
593 | struct cifsTconInfo *pTcon; | 598 | struct cifs_tcon *pTcon; |
594 | struct tcon_link *tlink; | 599 | struct tcon_link *tlink; |
595 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 600 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
596 | char *buf = NULL; | 601 | char *buf = NULL; |
@@ -735,10 +740,10 @@ static const struct inode_operations cifs_ipc_inode_ops = { | |||
735 | .lookup = cifs_lookup, | 740 | .lookup = cifs_lookup, |
736 | }; | 741 | }; |
737 | 742 | ||
738 | char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb, | 743 | char *cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, |
739 | struct cifsTconInfo *tcon) | 744 | struct cifs_tcon *tcon) |
740 | { | 745 | { |
741 | int pplen = cifs_sb->prepathlen; | 746 | int pplen = vol->prepath ? strlen(vol->prepath) : 0; |
742 | int dfsplen; | 747 | int dfsplen; |
743 | char *full_path = NULL; | 748 | char *full_path = NULL; |
744 | 749 | ||
@@ -772,7 +777,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb, | |||
772 | } | 777 | } |
773 | } | 778 | } |
774 | } | 779 | } |
775 | strncpy(full_path + dfsplen, cifs_sb->prepath, pplen); | 780 | strncpy(full_path + dfsplen, vol->prepath, pplen); |
776 | full_path[dfsplen + pplen] = 0; /* add trailing null */ | 781 | full_path[dfsplen + pplen] = 0; /* add trailing null */ |
777 | return full_path; | 782 | return full_path; |
778 | } | 783 | } |
@@ -878,25 +883,19 @@ retry_iget5_locked: | |||
878 | } | 883 | } |
879 | 884 | ||
880 | /* gets root inode */ | 885 | /* gets root inode */ |
881 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | 886 | struct inode *cifs_root_iget(struct super_block *sb) |
882 | { | 887 | { |
883 | int xid; | 888 | int xid; |
884 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 889 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
885 | struct inode *inode = NULL; | 890 | struct inode *inode = NULL; |
886 | long rc; | 891 | long rc; |
887 | char *full_path; | 892 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); |
888 | struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); | ||
889 | |||
890 | full_path = cifs_build_path_to_root(cifs_sb, tcon); | ||
891 | if (full_path == NULL) | ||
892 | return ERR_PTR(-ENOMEM); | ||
893 | 893 | ||
894 | xid = GetXid(); | 894 | xid = GetXid(); |
895 | if (tcon->unix_ext) | 895 | if (tcon->unix_ext) |
896 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); | 896 | rc = cifs_get_inode_info_unix(&inode, "", sb, xid); |
897 | else | 897 | else |
898 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, | 898 | rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL); |
899 | xid, NULL); | ||
900 | 899 | ||
901 | if (!inode) { | 900 | if (!inode) { |
902 | inode = ERR_PTR(rc); | 901 | inode = ERR_PTR(rc); |
@@ -922,7 +921,6 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
922 | } | 921 | } |
923 | 922 | ||
924 | out: | 923 | out: |
925 | kfree(full_path); | ||
926 | /* can not call macro FreeXid here since in a void func | 924 | /* can not call macro FreeXid here since in a void func |
927 | * TODO: This is no longer true | 925 | * TODO: This is no longer true |
928 | */ | 926 | */ |
@@ -943,7 +941,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, | |||
943 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 941 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
944 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 942 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
945 | struct tcon_link *tlink = NULL; | 943 | struct tcon_link *tlink = NULL; |
946 | struct cifsTconInfo *pTcon; | 944 | struct cifs_tcon *pTcon; |
947 | FILE_BASIC_INFO info_buf; | 945 | FILE_BASIC_INFO info_buf; |
948 | 946 | ||
949 | if (attrs == NULL) | 947 | if (attrs == NULL) |
@@ -1061,7 +1059,7 @@ cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid) | |||
1061 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1059 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
1062 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1060 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
1063 | struct tcon_link *tlink; | 1061 | struct tcon_link *tlink; |
1064 | struct cifsTconInfo *tcon; | 1062 | struct cifs_tcon *tcon; |
1065 | __u32 dosattr, origattr; | 1063 | __u32 dosattr, origattr; |
1066 | FILE_BASIC_INFO *info_buf = NULL; | 1064 | FILE_BASIC_INFO *info_buf = NULL; |
1067 | 1065 | ||
@@ -1179,7 +1177,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
1179 | struct super_block *sb = dir->i_sb; | 1177 | struct super_block *sb = dir->i_sb; |
1180 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 1178 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
1181 | struct tcon_link *tlink; | 1179 | struct tcon_link *tlink; |
1182 | struct cifsTconInfo *tcon; | 1180 | struct cifs_tcon *tcon; |
1183 | struct iattr *attrs = NULL; | 1181 | struct iattr *attrs = NULL; |
1184 | __u32 dosattr = 0, origattr = 0; | 1182 | __u32 dosattr = 0, origattr = 0; |
1185 | 1183 | ||
@@ -1277,7 +1275,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1277 | int xid; | 1275 | int xid; |
1278 | struct cifs_sb_info *cifs_sb; | 1276 | struct cifs_sb_info *cifs_sb; |
1279 | struct tcon_link *tlink; | 1277 | struct tcon_link *tlink; |
1280 | struct cifsTconInfo *pTcon; | 1278 | struct cifs_tcon *pTcon; |
1281 | char *full_path = NULL; | 1279 | char *full_path = NULL; |
1282 | struct inode *newinode = NULL; | 1280 | struct inode *newinode = NULL; |
1283 | struct cifs_fattr fattr; | 1281 | struct cifs_fattr fattr; |
@@ -1455,7 +1453,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
1455 | int xid; | 1453 | int xid; |
1456 | struct cifs_sb_info *cifs_sb; | 1454 | struct cifs_sb_info *cifs_sb; |
1457 | struct tcon_link *tlink; | 1455 | struct tcon_link *tlink; |
1458 | struct cifsTconInfo *pTcon; | 1456 | struct cifs_tcon *pTcon; |
1459 | char *full_path = NULL; | 1457 | char *full_path = NULL; |
1460 | struct cifsInodeInfo *cifsInode; | 1458 | struct cifsInodeInfo *cifsInode; |
1461 | 1459 | ||
@@ -1512,7 +1510,7 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, | |||
1512 | { | 1510 | { |
1513 | struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb); | 1511 | struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb); |
1514 | struct tcon_link *tlink; | 1512 | struct tcon_link *tlink; |
1515 | struct cifsTconInfo *pTcon; | 1513 | struct cifs_tcon *pTcon; |
1516 | __u16 srcfid; | 1514 | __u16 srcfid; |
1517 | int oplock, rc; | 1515 | int oplock, rc; |
1518 | 1516 | ||
@@ -1564,7 +1562,7 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
1564 | char *toName = NULL; | 1562 | char *toName = NULL; |
1565 | struct cifs_sb_info *cifs_sb; | 1563 | struct cifs_sb_info *cifs_sb; |
1566 | struct tcon_link *tlink; | 1564 | struct tcon_link *tlink; |
1567 | struct cifsTconInfo *tcon; | 1565 | struct cifs_tcon *tcon; |
1568 | FILE_UNIX_BASIC_INFO *info_buf_source = NULL; | 1566 | FILE_UNIX_BASIC_INFO *info_buf_source = NULL; |
1569 | FILE_UNIX_BASIC_INFO *info_buf_target; | 1567 | FILE_UNIX_BASIC_INFO *info_buf_target; |
1570 | int xid, rc, tmprc; | 1568 | int xid, rc, tmprc; |
@@ -1683,71 +1681,70 @@ cifs_inode_needs_reval(struct inode *inode) | |||
1683 | /* | 1681 | /* |
1684 | * Zap the cache. Called when invalid_mapping flag is set. | 1682 | * Zap the cache. Called when invalid_mapping flag is set. |
1685 | */ | 1683 | */ |
1686 | void | 1684 | int |
1687 | cifs_invalidate_mapping(struct inode *inode) | 1685 | cifs_invalidate_mapping(struct inode *inode) |
1688 | { | 1686 | { |
1689 | int rc; | 1687 | int rc = 0; |
1690 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | 1688 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); |
1691 | 1689 | ||
1692 | cifs_i->invalid_mapping = false; | 1690 | cifs_i->invalid_mapping = false; |
1693 | 1691 | ||
1694 | /* write back any cached data */ | ||
1695 | if (inode->i_mapping && inode->i_mapping->nrpages != 0) { | 1692 | if (inode->i_mapping && inode->i_mapping->nrpages != 0) { |
1696 | rc = filemap_write_and_wait(inode->i_mapping); | 1693 | rc = invalidate_inode_pages2(inode->i_mapping); |
1697 | mapping_set_error(inode->i_mapping, rc); | 1694 | if (rc) { |
1695 | cERROR(1, "%s: could not invalidate inode %p", __func__, | ||
1696 | inode); | ||
1697 | cifs_i->invalid_mapping = true; | ||
1698 | } | ||
1698 | } | 1699 | } |
1699 | invalidate_remote_inode(inode); | 1700 | |
1700 | cifs_fscache_reset_inode_cookie(inode); | 1701 | cifs_fscache_reset_inode_cookie(inode); |
1702 | return rc; | ||
1701 | } | 1703 | } |
1702 | 1704 | ||
1703 | int cifs_revalidate_file(struct file *filp) | 1705 | int cifs_revalidate_file_attr(struct file *filp) |
1704 | { | 1706 | { |
1705 | int rc = 0; | 1707 | int rc = 0; |
1706 | struct inode *inode = filp->f_path.dentry->d_inode; | 1708 | struct inode *inode = filp->f_path.dentry->d_inode; |
1707 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; | 1709 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; |
1708 | 1710 | ||
1709 | if (!cifs_inode_needs_reval(inode)) | 1711 | if (!cifs_inode_needs_reval(inode)) |
1710 | goto check_inval; | 1712 | return rc; |
1711 | 1713 | ||
1712 | if (tlink_tcon(cfile->tlink)->unix_ext) | 1714 | if (tlink_tcon(cfile->tlink)->unix_ext) |
1713 | rc = cifs_get_file_info_unix(filp); | 1715 | rc = cifs_get_file_info_unix(filp); |
1714 | else | 1716 | else |
1715 | rc = cifs_get_file_info(filp); | 1717 | rc = cifs_get_file_info(filp); |
1716 | 1718 | ||
1717 | check_inval: | ||
1718 | if (CIFS_I(inode)->invalid_mapping) | ||
1719 | cifs_invalidate_mapping(inode); | ||
1720 | |||
1721 | return rc; | 1719 | return rc; |
1722 | } | 1720 | } |
1723 | 1721 | ||
1724 | /* revalidate a dentry's inode attributes */ | 1722 | int cifs_revalidate_dentry_attr(struct dentry *dentry) |
1725 | int cifs_revalidate_dentry(struct dentry *dentry) | ||
1726 | { | 1723 | { |
1727 | int xid; | 1724 | int xid; |
1728 | int rc = 0; | 1725 | int rc = 0; |
1729 | char *full_path = NULL; | ||
1730 | struct inode *inode = dentry->d_inode; | 1726 | struct inode *inode = dentry->d_inode; |
1731 | struct super_block *sb = dentry->d_sb; | 1727 | struct super_block *sb = dentry->d_sb; |
1728 | char *full_path = NULL; | ||
1732 | 1729 | ||
1733 | if (inode == NULL) | 1730 | if (inode == NULL) |
1734 | return -ENOENT; | 1731 | return -ENOENT; |
1735 | 1732 | ||
1736 | xid = GetXid(); | ||
1737 | |||
1738 | if (!cifs_inode_needs_reval(inode)) | 1733 | if (!cifs_inode_needs_reval(inode)) |
1739 | goto check_inval; | 1734 | return rc; |
1735 | |||
1736 | xid = GetXid(); | ||
1740 | 1737 | ||
1741 | /* can not safely grab the rename sem here if rename calls revalidate | 1738 | /* can not safely grab the rename sem here if rename calls revalidate |
1742 | since that would deadlock */ | 1739 | since that would deadlock */ |
1743 | full_path = build_path_from_dentry(dentry); | 1740 | full_path = build_path_from_dentry(dentry); |
1744 | if (full_path == NULL) { | 1741 | if (full_path == NULL) { |
1745 | rc = -ENOMEM; | 1742 | rc = -ENOMEM; |
1746 | goto check_inval; | 1743 | goto out; |
1747 | } | 1744 | } |
1748 | 1745 | ||
1749 | cFYI(1, "Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld " | 1746 | cFYI(1, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time " |
1750 | "jiffies %ld", full_path, inode, inode->i_count.counter, | 1747 | "%ld jiffies %ld", full_path, inode, inode->i_count.counter, |
1751 | dentry, dentry->d_time, jiffies); | 1748 | dentry, dentry->d_time, jiffies); |
1752 | 1749 | ||
1753 | if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) | 1750 | if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) |
@@ -1756,41 +1753,83 @@ int cifs_revalidate_dentry(struct dentry *dentry) | |||
1756 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, | 1753 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, |
1757 | xid, NULL); | 1754 | xid, NULL); |
1758 | 1755 | ||
1759 | check_inval: | 1756 | out: |
1760 | if (CIFS_I(inode)->invalid_mapping) | ||
1761 | cifs_invalidate_mapping(inode); | ||
1762 | |||
1763 | kfree(full_path); | 1757 | kfree(full_path); |
1764 | FreeXid(xid); | 1758 | FreeXid(xid); |
1765 | return rc; | 1759 | return rc; |
1766 | } | 1760 | } |
1767 | 1761 | ||
1762 | int cifs_revalidate_file(struct file *filp) | ||
1763 | { | ||
1764 | int rc; | ||
1765 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
1766 | |||
1767 | rc = cifs_revalidate_file_attr(filp); | ||
1768 | if (rc) | ||
1769 | return rc; | ||
1770 | |||
1771 | if (CIFS_I(inode)->invalid_mapping) | ||
1772 | rc = cifs_invalidate_mapping(inode); | ||
1773 | return rc; | ||
1774 | } | ||
1775 | |||
1776 | /* revalidate a dentry's inode attributes */ | ||
1777 | int cifs_revalidate_dentry(struct dentry *dentry) | ||
1778 | { | ||
1779 | int rc; | ||
1780 | struct inode *inode = dentry->d_inode; | ||
1781 | |||
1782 | rc = cifs_revalidate_dentry_attr(dentry); | ||
1783 | if (rc) | ||
1784 | return rc; | ||
1785 | |||
1786 | if (CIFS_I(inode)->invalid_mapping) | ||
1787 | rc = cifs_invalidate_mapping(inode); | ||
1788 | return rc; | ||
1789 | } | ||
1790 | |||
1768 | int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, | 1791 | int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, |
1769 | struct kstat *stat) | 1792 | struct kstat *stat) |
1770 | { | 1793 | { |
1771 | struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); | 1794 | struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); |
1772 | struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); | 1795 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); |
1773 | int err = cifs_revalidate_dentry(dentry); | 1796 | struct inode *inode = dentry->d_inode; |
1774 | 1797 | int rc; | |
1775 | if (!err) { | ||
1776 | generic_fillattr(dentry->d_inode, stat); | ||
1777 | stat->blksize = CIFS_MAX_MSGSIZE; | ||
1778 | stat->ino = CIFS_I(dentry->d_inode)->uniqueid; | ||
1779 | 1798 | ||
1780 | /* | 1799 | /* |
1781 | * If on a multiuser mount without unix extensions, and the | 1800 | * We need to be sure that all dirty pages are written and the server |
1782 | * admin hasn't overridden them, set the ownership to the | 1801 | * has actual ctime, mtime and file length. |
1783 | * fsuid/fsgid of the current process. | 1802 | */ |
1784 | */ | 1803 | if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping && |
1785 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) && | 1804 | inode->i_mapping->nrpages != 0) { |
1786 | !tcon->unix_ext) { | 1805 | rc = filemap_fdatawait(inode->i_mapping); |
1787 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) | 1806 | if (rc) { |
1788 | stat->uid = current_fsuid(); | 1807 | mapping_set_error(inode->i_mapping, rc); |
1789 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) | 1808 | return rc; |
1790 | stat->gid = current_fsgid(); | ||
1791 | } | 1809 | } |
1792 | } | 1810 | } |
1793 | return err; | 1811 | |
1812 | rc = cifs_revalidate_dentry_attr(dentry); | ||
1813 | if (rc) | ||
1814 | return rc; | ||
1815 | |||
1816 | generic_fillattr(inode, stat); | ||
1817 | stat->blksize = CIFS_MAX_MSGSIZE; | ||
1818 | stat->ino = CIFS_I(inode)->uniqueid; | ||
1819 | |||
1820 | /* | ||
1821 | * If on a multiuser mount without unix extensions, and the admin hasn't | ||
1822 | * overridden them, set the ownership to the fsuid/fsgid of the current | ||
1823 | * process. | ||
1824 | */ | ||
1825 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) && | ||
1826 | !tcon->unix_ext) { | ||
1827 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) | ||
1828 | stat->uid = current_fsuid(); | ||
1829 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) | ||
1830 | stat->gid = current_fsgid(); | ||
1831 | } | ||
1832 | return rc; | ||
1794 | } | 1833 | } |
1795 | 1834 | ||
1796 | static int cifs_truncate_page(struct address_space *mapping, loff_t from) | 1835 | static int cifs_truncate_page(struct address_space *mapping, loff_t from) |
@@ -1831,7 +1870,8 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1831 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1870 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
1832 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1871 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
1833 | struct tcon_link *tlink = NULL; | 1872 | struct tcon_link *tlink = NULL; |
1834 | struct cifsTconInfo *pTcon = NULL; | 1873 | struct cifs_tcon *pTcon = NULL; |
1874 | struct cifs_io_parms io_parms; | ||
1835 | 1875 | ||
1836 | /* | 1876 | /* |
1837 | * To avoid spurious oplock breaks from server, in the case of | 1877 | * To avoid spurious oplock breaks from server, in the case of |
@@ -1853,8 +1893,14 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1853 | cFYI(1, "SetFSize for attrs rc = %d", rc); | 1893 | cFYI(1, "SetFSize for attrs rc = %d", rc); |
1854 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | 1894 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { |
1855 | unsigned int bytes_written; | 1895 | unsigned int bytes_written; |
1856 | rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size, | 1896 | |
1857 | &bytes_written, NULL, NULL, 1); | 1897 | io_parms.netfid = nfid; |
1898 | io_parms.pid = npid; | ||
1899 | io_parms.tcon = pTcon; | ||
1900 | io_parms.offset = 0; | ||
1901 | io_parms.length = attrs->ia_size; | ||
1902 | rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, | ||
1903 | NULL, NULL, 1); | ||
1858 | cFYI(1, "Wrt seteof rc %d", rc); | 1904 | cFYI(1, "Wrt seteof rc %d", rc); |
1859 | } | 1905 | } |
1860 | } else | 1906 | } else |
@@ -1889,10 +1935,15 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1889 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1935 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1890 | if (rc == 0) { | 1936 | if (rc == 0) { |
1891 | unsigned int bytes_written; | 1937 | unsigned int bytes_written; |
1892 | rc = CIFSSMBWrite(xid, pTcon, netfid, 0, | 1938 | |
1893 | attrs->ia_size, | 1939 | io_parms.netfid = netfid; |
1894 | &bytes_written, NULL, | 1940 | io_parms.pid = current->tgid; |
1895 | NULL, 1); | 1941 | io_parms.tcon = pTcon; |
1942 | io_parms.offset = 0; | ||
1943 | io_parms.length = attrs->ia_size; | ||
1944 | rc = CIFSSMBWrite(xid, &io_parms, | ||
1945 | &bytes_written, | ||
1946 | NULL, NULL, 1); | ||
1896 | cFYI(1, "wrt seteof rc %d", rc); | 1947 | cFYI(1, "wrt seteof rc %d", rc); |
1897 | CIFSSMBClose(xid, pTcon, netfid); | 1948 | CIFSSMBClose(xid, pTcon, netfid); |
1898 | } | 1949 | } |
@@ -1920,7 +1971,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1920 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1971 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
1921 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1972 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
1922 | struct tcon_link *tlink; | 1973 | struct tcon_link *tlink; |
1923 | struct cifsTconInfo *pTcon; | 1974 | struct cifs_tcon *pTcon; |
1924 | struct cifs_unix_set_info_args *args = NULL; | 1975 | struct cifs_unix_set_info_args *args = NULL; |
1925 | struct cifsFileInfo *open_file; | 1976 | struct cifsFileInfo *open_file; |
1926 | 1977 | ||
@@ -2206,7 +2257,7 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
2206 | { | 2257 | { |
2207 | struct inode *inode = direntry->d_inode; | 2258 | struct inode *inode = direntry->d_inode; |
2208 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 2259 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
2209 | struct cifsTconInfo *pTcon = cifs_sb_master_tcon(cifs_sb); | 2260 | struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb); |
2210 | 2261 | ||
2211 | if (pTcon->unix_ext) | 2262 | if (pTcon->unix_ext) |
2212 | return cifs_setattr_unix(direntry, attrs); | 2263 | return cifs_setattr_unix(direntry, attrs); |