aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r--fs/cifs/inode.c419
1 files changed, 279 insertions, 140 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 46e54d39461d..28a22092d450 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -737,7 +737,7 @@ psx_del_no_retry:
737 /* ATTRS set to normal clears r/o bit */ 737 /* ATTRS set to normal clears r/o bit */
738 pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL); 738 pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
739 if (!(pTcon->ses->flags & CIFS_SES_NT4)) 739 if (!(pTcon->ses->flags & CIFS_SES_NT4))
740 rc = CIFSSMBSetTimes(xid, pTcon, full_path, 740 rc = CIFSSMBSetPathInfo(xid, pTcon, full_path,
741 pinfo_buf, 741 pinfo_buf,
742 cifs_sb->local_nls, 742 cifs_sb->local_nls,
743 cifs_sb->mnt_cifs_flags & 743 cifs_sb->mnt_cifs_flags &
@@ -767,9 +767,10 @@ psx_del_no_retry:
767 cifs_sb->mnt_cifs_flags & 767 cifs_sb->mnt_cifs_flags &
768 CIFS_MOUNT_MAP_SPECIAL_CHR); 768 CIFS_MOUNT_MAP_SPECIAL_CHR);
769 if (rc == 0) { 769 if (rc == 0) {
770 rc = CIFSSMBSetFileTimes(xid, pTcon, 770 rc = CIFSSMBSetFileInfo(xid, pTcon,
771 pinfo_buf, 771 pinfo_buf,
772 netfid); 772 netfid,
773 current->tgid);
773 CIFSSMBClose(xid, pTcon, netfid); 774 CIFSSMBClose(xid, pTcon, netfid);
774 } 775 }
775 } 776 }
@@ -984,32 +985,41 @@ mkdir_get_info:
984 * failed to get it from the server or was set bogus */ 985 * failed to get it from the server or was set bogus */
985 if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) 986 if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
986 direntry->d_inode->i_nlink = 2; 987 direntry->d_inode->i_nlink = 2;
988
987 mode &= ~current->fs->umask; 989 mode &= ~current->fs->umask;
990 /* must turn on setgid bit if parent dir has it */
991 if (inode->i_mode & S_ISGID)
992 mode |= S_ISGID;
993
988 if (pTcon->unix_ext) { 994 if (pTcon->unix_ext) {
995 struct cifs_unix_set_info_args args = {
996 .mode = mode,
997 .ctime = NO_CHANGE_64,
998 .atime = NO_CHANGE_64,
999 .mtime = NO_CHANGE_64,
1000 .device = 0,
1001 };
989 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 1002 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
990 CIFSSMBUnixSetPerms(xid, pTcon, full_path, 1003 args.uid = (__u64)current->fsuid;
991 mode, 1004 if (inode->i_mode & S_ISGID)
992 (__u64)current->fsuid, 1005 args.gid = (__u64)inode->i_gid;
993 (__u64)current->fsgid, 1006 else
994 0 /* dev_t */, 1007 args.gid = (__u64)current->fsgid;
995 cifs_sb->local_nls,
996 cifs_sb->mnt_cifs_flags &
997 CIFS_MOUNT_MAP_SPECIAL_CHR);
998 } else { 1008 } else {
999 CIFSSMBUnixSetPerms(xid, pTcon, full_path, 1009 args.uid = NO_CHANGE_64;
1000 mode, (__u64)-1, 1010 args.gid = NO_CHANGE_64;
1001 (__u64)-1, 0 /* dev_t */,
1002 cifs_sb->local_nls,
1003 cifs_sb->mnt_cifs_flags &
1004 CIFS_MOUNT_MAP_SPECIAL_CHR);
1005 } 1011 }
1012 CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args,
1013 cifs_sb->local_nls,
1014 cifs_sb->mnt_cifs_flags &
1015 CIFS_MOUNT_MAP_SPECIAL_CHR);
1006 } else { 1016 } else {
1007 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && 1017 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
1008 (mode & S_IWUGO) == 0) { 1018 (mode & S_IWUGO) == 0) {
1009 FILE_BASIC_INFO pInfo; 1019 FILE_BASIC_INFO pInfo;
1010 memset(&pInfo, 0, sizeof(pInfo)); 1020 memset(&pInfo, 0, sizeof(pInfo));
1011 pInfo.Attributes = cpu_to_le32(ATTR_READONLY); 1021 pInfo.Attributes = cpu_to_le32(ATTR_READONLY);
1012 CIFSSMBSetTimes(xid, pTcon, full_path, 1022 CIFSSMBSetPathInfo(xid, pTcon, full_path,
1013 &pInfo, cifs_sb->local_nls, 1023 &pInfo, cifs_sb->local_nls,
1014 cifs_sb->mnt_cifs_flags & 1024 cifs_sb->mnt_cifs_flags &
1015 CIFS_MOUNT_MAP_SPECIAL_CHR); 1025 CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -1024,8 +1034,12 @@ mkdir_get_info:
1024 CIFS_MOUNT_SET_UID) { 1034 CIFS_MOUNT_SET_UID) {
1025 direntry->d_inode->i_uid = 1035 direntry->d_inode->i_uid =
1026 current->fsuid; 1036 current->fsuid;
1027 direntry->d_inode->i_gid = 1037 if (inode->i_mode & S_ISGID)
1028 current->fsgid; 1038 direntry->d_inode->i_gid =
1039 inode->i_gid;
1040 else
1041 direntry->d_inode->i_gid =
1042 current->fsgid;
1029 } 1043 }
1030 } 1044 }
1031 } 1045 }
@@ -1310,10 +1324,11 @@ int cifs_revalidate(struct dentry *direntry)
1310/* if (S_ISDIR(direntry->d_inode->i_mode)) 1324/* if (S_ISDIR(direntry->d_inode->i_mode))
1311 shrink_dcache_parent(direntry); */ 1325 shrink_dcache_parent(direntry); */
1312 if (S_ISREG(direntry->d_inode->i_mode)) { 1326 if (S_ISREG(direntry->d_inode->i_mode)) {
1313 if (direntry->d_inode->i_mapping) 1327 if (direntry->d_inode->i_mapping) {
1314 wbrc = filemap_fdatawait(direntry->d_inode->i_mapping); 1328 wbrc = filemap_fdatawait(direntry->d_inode->i_mapping);
1315 if (wbrc) 1329 if (wbrc)
1316 CIFS_I(direntry->d_inode)->write_behind_rc = wbrc; 1330 CIFS_I(direntry->d_inode)->write_behind_rc = wbrc;
1331 }
1317 /* may eventually have to do this for open files too */ 1332 /* may eventually have to do this for open files too */
1318 if (list_empty(&(cifsInode->openFileList))) { 1333 if (list_empty(&(cifsInode->openFileList))) {
1319 /* changed on server - flush read ahead pages */ 1334 /* changed on server - flush read ahead pages */
@@ -1489,30 +1504,228 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
1489 return rc; 1504 return rc;
1490} 1505}
1491 1506
1492int cifs_setattr(struct dentry *direntry, struct iattr *attrs) 1507static int
1508cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
1509 char *full_path, __u32 dosattr)
1510{
1511 int rc;
1512 int oplock = 0;
1513 __u16 netfid;
1514 __u32 netpid;
1515 bool set_time = false;
1516 struct cifsFileInfo *open_file;
1517 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1518 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1519 struct cifsTconInfo *pTcon = cifs_sb->tcon;
1520 FILE_BASIC_INFO info_buf;
1521
1522 if (attrs->ia_valid & ATTR_ATIME) {
1523 set_time = true;
1524 info_buf.LastAccessTime =
1525 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
1526 } else
1527 info_buf.LastAccessTime = 0;
1528
1529 if (attrs->ia_valid & ATTR_MTIME) {
1530 set_time = true;
1531 info_buf.LastWriteTime =
1532 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1533 } else
1534 info_buf.LastWriteTime = 0;
1535
1536 /*
1537 * Samba throws this field away, but windows may actually use it.
1538 * Do not set ctime unless other time stamps are changed explicitly
1539 * (i.e. by utimes()) since we would then have a mix of client and
1540 * server times.
1541 */
1542 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
1543 cFYI(1, ("CIFS - CTIME changed"));
1544 info_buf.ChangeTime =
1545 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1546 } else
1547 info_buf.ChangeTime = 0;
1548
1549 info_buf.CreationTime = 0; /* don't change */
1550 info_buf.Attributes = cpu_to_le32(dosattr);
1551
1552 /*
1553 * If the file is already open for write, just use that fileid
1554 */
1555 open_file = find_writable_file(cifsInode);
1556 if (open_file) {
1557 netfid = open_file->netfid;
1558 netpid = open_file->pid;
1559 goto set_via_filehandle;
1560 }
1561
1562 /*
1563 * NT4 apparently returns success on this call, but it doesn't
1564 * really work.
1565 */
1566 if (!(pTcon->ses->flags & CIFS_SES_NT4)) {
1567 rc = CIFSSMBSetPathInfo(xid, pTcon, full_path,
1568 &info_buf, cifs_sb->local_nls,
1569 cifs_sb->mnt_cifs_flags &
1570 CIFS_MOUNT_MAP_SPECIAL_CHR);
1571 if (rc != -EOPNOTSUPP && rc != -EINVAL)
1572 goto out;
1573 }
1574
1575 cFYI(1, ("calling SetFileInfo since SetPathInfo for "
1576 "times not supported by this server"));
1577 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
1578 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1579 CREATE_NOT_DIR, &netfid, &oplock,
1580 NULL, cifs_sb->local_nls,
1581 cifs_sb->mnt_cifs_flags &
1582 CIFS_MOUNT_MAP_SPECIAL_CHR);
1583
1584 if (rc != 0) {
1585 if (rc == -EIO)
1586 rc = -EINVAL;
1587 goto out;
1588 }
1589
1590 netpid = current->tgid;
1591
1592set_via_filehandle:
1593 rc = CIFSSMBSetFileInfo(xid, pTcon, &info_buf, netfid, netpid);
1594 if (open_file == NULL)
1595 CIFSSMBClose(xid, pTcon, netfid);
1596 else
1597 atomic_dec(&open_file->wrtPending);
1598out:
1599 return rc;
1600}
1601
1602static int
1603cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1493{ 1604{
1605 int rc;
1494 int xid; 1606 int xid;
1495 struct cifs_sb_info *cifs_sb;
1496 struct cifsTconInfo *pTcon;
1497 char *full_path = NULL; 1607 char *full_path = NULL;
1498 int rc = -EACCES;
1499 FILE_BASIC_INFO time_buf;
1500 bool set_time = false;
1501 bool set_dosattr = false;
1502 __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
1503 __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
1504 __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
1505 struct cifsInodeInfo *cifsInode;
1506 struct inode *inode = direntry->d_inode; 1608 struct inode *inode = direntry->d_inode;
1609 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1610 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1611 struct cifsTconInfo *pTcon = cifs_sb->tcon;
1612 struct cifs_unix_set_info_args *args = NULL;
1613
1614 cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x",
1615 direntry->d_name.name, attrs->ia_valid));
1616
1617 xid = GetXid();
1618
1619 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
1620 /* check if we have permission to change attrs */
1621 rc = inode_change_ok(inode, attrs);
1622 if (rc < 0)
1623 goto out;
1624 else
1625 rc = 0;
1626 }
1627
1628 full_path = build_path_from_dentry(direntry);
1629 if (full_path == NULL) {
1630 rc = -ENOMEM;
1631 goto out;
1632 }
1633
1634 if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) {
1635 /*
1636 Flush data before changing file size or changing the last
1637 write time of the file on the server. If the
1638 flush returns error, store it to report later and continue.
1639 BB: This should be smarter. Why bother flushing pages that
1640 will be truncated anyway? Also, should we error out here if
1641 the flush returns error?
1642 */
1643 rc = filemap_write_and_wait(inode->i_mapping);
1644 if (rc != 0) {
1645 cifsInode->write_behind_rc = rc;
1646 rc = 0;
1647 }
1648 }
1649
1650 if (attrs->ia_valid & ATTR_SIZE) {
1651 rc = cifs_set_file_size(inode, attrs, xid, full_path);
1652 if (rc != 0)
1653 goto out;
1654 }
1655
1656 /* skip mode change if it's just for clearing setuid/setgid */
1657 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
1658 attrs->ia_valid &= ~ATTR_MODE;
1659
1660 args = kmalloc(sizeof(*args), GFP_KERNEL);
1661 if (args == NULL) {
1662 rc = -ENOMEM;
1663 goto out;
1664 }
1665
1666 /* set up the struct */
1667 if (attrs->ia_valid & ATTR_MODE)
1668 args->mode = attrs->ia_mode;
1669 else
1670 args->mode = NO_CHANGE_64;
1671
1672 if (attrs->ia_valid & ATTR_UID)
1673 args->uid = attrs->ia_uid;
1674 else
1675 args->uid = NO_CHANGE_64;
1676
1677 if (attrs->ia_valid & ATTR_GID)
1678 args->gid = attrs->ia_gid;
1679 else
1680 args->gid = NO_CHANGE_64;
1681
1682 if (attrs->ia_valid & ATTR_ATIME)
1683 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
1684 else
1685 args->atime = NO_CHANGE_64;
1686
1687 if (attrs->ia_valid & ATTR_MTIME)
1688 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
1689 else
1690 args->mtime = NO_CHANGE_64;
1691
1692 if (attrs->ia_valid & ATTR_CTIME)
1693 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
1694 else
1695 args->ctime = NO_CHANGE_64;
1696
1697 args->device = 0;
1698 rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, args,
1699 cifs_sb->local_nls,
1700 cifs_sb->mnt_cifs_flags &
1701 CIFS_MOUNT_MAP_SPECIAL_CHR);
1702
1703 if (!rc)
1704 rc = inode_setattr(inode, attrs);
1705out:
1706 kfree(args);
1707 kfree(full_path);
1708 FreeXid(xid);
1709 return rc;
1710}
1711
1712static int
1713cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
1714{
1715 int xid;
1716 struct inode *inode = direntry->d_inode;
1717 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1718 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1719 char *full_path = NULL;
1720 int rc = -EACCES;
1721 __u32 dosattr = 0;
1722 __u64 mode = NO_CHANGE_64;
1507 1723
1508 xid = GetXid(); 1724 xid = GetXid();
1509 1725
1510 cFYI(1, ("setattr on file %s attrs->iavalid 0x%x", 1726 cFYI(1, ("setattr on file %s attrs->iavalid 0x%x",
1511 direntry->d_name.name, attrs->ia_valid)); 1727 direntry->d_name.name, attrs->ia_valid));
1512 1728
1513 cifs_sb = CIFS_SB(inode->i_sb);
1514 pTcon = cifs_sb->tcon;
1515
1516 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { 1729 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
1517 /* check if we have permission to change attrs */ 1730 /* check if we have permission to change attrs */
1518 rc = inode_change_ok(inode, attrs); 1731 rc = inode_change_ok(inode, attrs);
@@ -1528,7 +1741,6 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1528 FreeXid(xid); 1741 FreeXid(xid);
1529 return -ENOMEM; 1742 return -ENOMEM;
1530 } 1743 }
1531 cifsInode = CIFS_I(inode);
1532 1744
1533 if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { 1745 if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) {
1534 /* 1746 /*
@@ -1559,21 +1771,8 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1559 * CIFSACL support + proper Windows to Unix idmapping, we may be 1771 * CIFSACL support + proper Windows to Unix idmapping, we may be
1560 * able to support this in the future. 1772 * able to support this in the future.
1561 */ 1773 */
1562 if (!pTcon->unix_ext && 1774 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
1563 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
1564 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID); 1775 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
1565 } else {
1566 if (attrs->ia_valid & ATTR_UID) {
1567 cFYI(1, ("UID changed to %d", attrs->ia_uid));
1568 uid = attrs->ia_uid;
1569 }
1570 if (attrs->ia_valid & ATTR_GID) {
1571 cFYI(1, ("GID changed to %d", attrs->ia_gid));
1572 gid = attrs->ia_gid;
1573 }
1574 }
1575
1576 time_buf.Attributes = 0;
1577 1776
1578 /* skip mode change if it's just for clearing setuid/setgid */ 1777 /* skip mode change if it's just for clearing setuid/setgid */
1579 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) 1778 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
@@ -1584,13 +1783,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1584 mode = attrs->ia_mode; 1783 mode = attrs->ia_mode;
1585 } 1784 }
1586 1785
1587 if ((pTcon->unix_ext) 1786 if (attrs->ia_valid & ATTR_MODE) {
1588 && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
1589 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
1590 0 /* dev_t */, cifs_sb->local_nls,
1591 cifs_sb->mnt_cifs_flags &
1592 CIFS_MOUNT_MAP_SPECIAL_CHR);
1593 else if (attrs->ia_valid & ATTR_MODE) {
1594 rc = 0; 1787 rc = 0;
1595#ifdef CONFIG_CIFS_EXPERIMENTAL 1788#ifdef CONFIG_CIFS_EXPERIMENTAL
1596 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) 1789 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
@@ -1599,24 +1792,19 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1599#endif 1792#endif
1600 if (((mode & S_IWUGO) == 0) && 1793 if (((mode & S_IWUGO) == 0) &&
1601 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { 1794 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
1602 set_dosattr = true; 1795
1603 time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs | 1796 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
1604 ATTR_READONLY); 1797
1605 /* fix up mode if we're not using dynperm */ 1798 /* fix up mode if we're not using dynperm */
1606 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) 1799 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
1607 attrs->ia_mode = inode->i_mode & ~S_IWUGO; 1800 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
1608 } else if ((mode & S_IWUGO) && 1801 } else if ((mode & S_IWUGO) &&
1609 (cifsInode->cifsAttrs & ATTR_READONLY)) { 1802 (cifsInode->cifsAttrs & ATTR_READONLY)) {
1610 /* If file is readonly on server, we would 1803
1611 not be able to write to it - so if any write 1804 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
1612 bit is enabled for user or group or other we 1805 /* Attributes of 0 are ignored */
1613 need to at least try to remove r/o dos attr */ 1806 if (dosattr == 0)
1614 set_dosattr = true; 1807 dosattr |= ATTR_NORMAL;
1615 time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs &
1616 (~ATTR_READONLY));
1617 /* Windows ignores set to zero */
1618 if (time_buf.Attributes == 0)
1619 time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL);
1620 1808
1621 /* reset local inode permissions to normal */ 1809 /* reset local inode permissions to normal */
1622 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { 1810 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
@@ -1634,82 +1822,18 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1634 } 1822 }
1635 } 1823 }
1636 1824
1637 if (attrs->ia_valid & ATTR_ATIME) { 1825 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
1638 set_time = true; 1826 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
1639 time_buf.LastAccessTime = 1827 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
1640 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime)); 1828 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
1641 } else
1642 time_buf.LastAccessTime = 0;
1643
1644 if (attrs->ia_valid & ATTR_MTIME) {
1645 set_time = true;
1646 time_buf.LastWriteTime =
1647 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1648 } else
1649 time_buf.LastWriteTime = 0;
1650 /* Do not set ctime explicitly unless other time
1651 stamps are changed explicitly (i.e. by utime()
1652 since we would then have a mix of client and
1653 server times */
1654 1829
1655 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
1656 set_time = true;
1657 /* Although Samba throws this field away
1658 it may be useful to Windows - but we do
1659 not want to set ctime unless some other
1660 timestamp is changing */
1661 cFYI(1, ("CIFS - CTIME changed"));
1662 time_buf.ChangeTime =
1663 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1664 } else
1665 time_buf.ChangeTime = 0;
1666
1667 if (set_time || set_dosattr) {
1668 time_buf.CreationTime = 0; /* do not change */
1669 /* In the future we should experiment - try setting timestamps
1670 via Handle (SetFileInfo) instead of by path */
1671 if (!(pTcon->ses->flags & CIFS_SES_NT4))
1672 rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
1673 cifs_sb->local_nls,
1674 cifs_sb->mnt_cifs_flags &
1675 CIFS_MOUNT_MAP_SPECIAL_CHR);
1676 else
1677 rc = -EOPNOTSUPP;
1678
1679 if (rc == -EOPNOTSUPP) {
1680 int oplock = 0;
1681 __u16 netfid;
1682
1683 cFYI(1, ("calling SetFileInfo since SetPathInfo for "
1684 "times not supported by this server"));
1685 /* BB we could scan to see if we already have it open
1686 and pass in pid of opener to function */
1687 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
1688 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1689 CREATE_NOT_DIR, &netfid, &oplock,
1690 NULL, cifs_sb->local_nls,
1691 cifs_sb->mnt_cifs_flags &
1692 CIFS_MOUNT_MAP_SPECIAL_CHR);
1693 if (rc == 0) {
1694 rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
1695 netfid);
1696 CIFSSMBClose(xid, pTcon, netfid);
1697 } else {
1698 /* BB For even older servers we could convert time_buf
1699 into old DOS style which uses two second
1700 granularity */
1701
1702 /* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path,
1703 &time_buf, cifs_sb->local_nls); */
1704 }
1705 }
1706 /* Even if error on time set, no sense failing the call if 1830 /* Even if error on time set, no sense failing the call if
1707 the server would set the time to a reasonable value anyway, 1831 the server would set the time to a reasonable value anyway,
1708 and this check ensures that we are not being called from 1832 and this check ensures that we are not being called from
1709 sys_utimes in which case we ought to fail the call back to 1833 sys_utimes in which case we ought to fail the call back to
1710 the user when the server rejects the call */ 1834 the user when the server rejects the call */
1711 if ((rc) && (attrs->ia_valid & 1835 if ((rc) && (attrs->ia_valid &
1712 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE))) 1836 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
1713 rc = 0; 1837 rc = 0;
1714 } 1838 }
1715 1839
@@ -1723,6 +1847,21 @@ cifs_setattr_exit:
1723 return rc; 1847 return rc;
1724} 1848}
1725 1849
1850int
1851cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1852{
1853 struct inode *inode = direntry->d_inode;
1854 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1855 struct cifsTconInfo *pTcon = cifs_sb->tcon;
1856
1857 if (pTcon->unix_ext)
1858 return cifs_setattr_unix(direntry, attrs);
1859
1860 return cifs_setattr_nounix(direntry, attrs);
1861
1862 /* BB: add cifs_setattr_legacy for really old servers */
1863}
1864
1726#if 0 1865#if 0
1727void cifs_delete_inode(struct inode *inode) 1866void cifs_delete_inode(struct inode *inode)
1728{ 1867{