diff options
| author | Jeff Layton <jlayton@redhat.com> | 2008-08-02 07:26:12 -0400 |
|---|---|---|
| committer | Steve French <sfrench@us.ibm.com> | 2008-08-06 18:14:52 -0400 |
| commit | 3fe5c1dd0a8bf3756c447a28a578593176949d1d (patch) | |
| tree | a0c71c7b5f4c618496381d64c8fab456c95b76c6 | |
| parent | 26b994fad6a062697846a861ecc008447409dfb6 (diff) | |
spin off cifs_setattr with unix extensions to its own function
Create a new cifs_setattr_unix function to handle a setattr when unix
extensions are enabled and have cifs_setattr call it. Also, clean up
variable declarations in cifs_setattr.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
| -rw-r--r-- | fs/cifs/inode.c | 157 |
1 files changed, 119 insertions, 38 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 6d911896d74c..f68d1abe13e6 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -1504,30 +1504,138 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
| 1504 | return rc; | 1504 | return rc; |
| 1505 | } | 1505 | } |
| 1506 | 1506 | ||
| 1507 | static int | ||
| 1508 | cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | ||
| 1509 | { | ||
| 1510 | int rc; | ||
| 1511 | int xid; | ||
| 1512 | char *full_path = NULL; | ||
| 1513 | struct inode *inode = direntry->d_inode; | ||
| 1514 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | ||
| 1515 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
| 1516 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | ||
| 1517 | struct cifs_unix_set_info_args *args = NULL; | ||
| 1518 | |||
| 1519 | cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", | ||
| 1520 | direntry->d_name.name, attrs->ia_valid)); | ||
| 1521 | |||
| 1522 | xid = GetXid(); | ||
| 1523 | |||
| 1524 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { | ||
| 1525 | /* check if we have permission to change attrs */ | ||
| 1526 | rc = inode_change_ok(inode, attrs); | ||
| 1527 | if (rc < 0) | ||
| 1528 | goto out; | ||
| 1529 | else | ||
| 1530 | rc = 0; | ||
| 1531 | } | ||
| 1532 | |||
| 1533 | full_path = build_path_from_dentry(direntry); | ||
| 1534 | if (full_path == NULL) { | ||
| 1535 | rc = -ENOMEM; | ||
| 1536 | goto out; | ||
| 1537 | } | ||
| 1538 | |||
| 1539 | if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { | ||
| 1540 | /* | ||
| 1541 | Flush data before changing file size or changing the last | ||
| 1542 | write time of the file on the server. If the | ||
| 1543 | flush returns error, store it to report later and continue. | ||
| 1544 | BB: This should be smarter. Why bother flushing pages that | ||
| 1545 | will be truncated anyway? Also, should we error out here if | ||
| 1546 | the flush returns error? | ||
| 1547 | */ | ||
| 1548 | rc = filemap_write_and_wait(inode->i_mapping); | ||
| 1549 | if (rc != 0) { | ||
| 1550 | cifsInode->write_behind_rc = rc; | ||
| 1551 | rc = 0; | ||
| 1552 | } | ||
| 1553 | } | ||
| 1554 | |||
| 1555 | if (attrs->ia_valid & ATTR_SIZE) { | ||
| 1556 | rc = cifs_set_file_size(inode, attrs, xid, full_path); | ||
| 1557 | if (rc != 0) | ||
| 1558 | goto out; | ||
| 1559 | } | ||
| 1560 | |||
| 1561 | /* skip mode change if it's just for clearing setuid/setgid */ | ||
| 1562 | if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) | ||
| 1563 | attrs->ia_valid &= ~ATTR_MODE; | ||
| 1564 | |||
| 1565 | args = kmalloc(sizeof(*args), GFP_KERNEL); | ||
| 1566 | if (args == NULL) { | ||
| 1567 | rc = -ENOMEM; | ||
| 1568 | goto out; | ||
| 1569 | } | ||
| 1570 | |||
| 1571 | /* set up the struct */ | ||
| 1572 | if (attrs->ia_valid & ATTR_MODE) | ||
| 1573 | args->mode = attrs->ia_mode; | ||
| 1574 | else | ||
| 1575 | args->mode = NO_CHANGE_64; | ||
| 1576 | |||
| 1577 | if (attrs->ia_valid & ATTR_UID) | ||
| 1578 | args->uid = attrs->ia_uid; | ||
| 1579 | else | ||
| 1580 | args->uid = NO_CHANGE_64; | ||
| 1581 | |||
| 1582 | if (attrs->ia_valid & ATTR_GID) | ||
| 1583 | args->gid = attrs->ia_gid; | ||
| 1584 | else | ||
| 1585 | args->gid = NO_CHANGE_64; | ||
| 1586 | |||
| 1587 | if (attrs->ia_valid & ATTR_ATIME) | ||
| 1588 | args->atime = cifs_UnixTimeToNT(attrs->ia_atime); | ||
| 1589 | else | ||
| 1590 | args->atime = NO_CHANGE_64; | ||
| 1591 | |||
| 1592 | if (attrs->ia_valid & ATTR_MTIME) | ||
| 1593 | args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime); | ||
| 1594 | else | ||
| 1595 | args->mtime = NO_CHANGE_64; | ||
| 1596 | |||
| 1597 | if (attrs->ia_valid & ATTR_CTIME) | ||
| 1598 | args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime); | ||
| 1599 | else | ||
| 1600 | args->ctime = NO_CHANGE_64; | ||
| 1601 | |||
| 1602 | args->device = 0; | ||
| 1603 | rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, args, | ||
| 1604 | cifs_sb->local_nls, | ||
| 1605 | cifs_sb->mnt_cifs_flags & | ||
| 1606 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 1607 | |||
| 1608 | if (!rc) | ||
| 1609 | rc = inode_setattr(inode, attrs); | ||
| 1610 | out: | ||
| 1611 | kfree(args); | ||
| 1612 | kfree(full_path); | ||
| 1613 | FreeXid(xid); | ||
| 1614 | return rc; | ||
| 1615 | } | ||
| 1616 | |||
| 1507 | int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | 1617 | int cifs_setattr(struct dentry *direntry, struct iattr *attrs) |
| 1508 | { | 1618 | { |
| 1509 | int xid; | 1619 | int xid; |
| 1510 | struct cifs_sb_info *cifs_sb; | 1620 | struct inode *inode = direntry->d_inode; |
| 1511 | struct cifsTconInfo *pTcon; | 1621 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
| 1622 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | ||
| 1623 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | ||
| 1512 | char *full_path = NULL; | 1624 | char *full_path = NULL; |
| 1513 | int rc = -EACCES; | 1625 | int rc = -EACCES; |
| 1514 | FILE_BASIC_INFO time_buf; | 1626 | FILE_BASIC_INFO time_buf; |
| 1515 | bool set_time = false; | 1627 | bool set_time = false; |
| 1516 | bool set_dosattr = false; | 1628 | bool set_dosattr = false; |
| 1517 | __u64 mode = NO_CHANGE_64; | 1629 | __u64 mode = NO_CHANGE_64; |
| 1518 | __u64 uid = NO_CHANGE_64; | 1630 | |
| 1519 | __u64 gid = NO_CHANGE_64; | 1631 | if (pTcon->unix_ext) |
| 1520 | struct cifsInodeInfo *cifsInode; | 1632 | return cifs_setattr_unix(direntry, attrs); |
| 1521 | struct inode *inode = direntry->d_inode; | ||
| 1522 | 1633 | ||
| 1523 | xid = GetXid(); | 1634 | xid = GetXid(); |
| 1524 | 1635 | ||
| 1525 | cFYI(1, ("setattr on file %s attrs->iavalid 0x%x", | 1636 | cFYI(1, ("setattr on file %s attrs->iavalid 0x%x", |
| 1526 | direntry->d_name.name, attrs->ia_valid)); | 1637 | direntry->d_name.name, attrs->ia_valid)); |
| 1527 | 1638 | ||
| 1528 | cifs_sb = CIFS_SB(inode->i_sb); | ||
| 1529 | pTcon = cifs_sb->tcon; | ||
| 1530 | |||
| 1531 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { | 1639 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { |
| 1532 | /* check if we have permission to change attrs */ | 1640 | /* check if we have permission to change attrs */ |
| 1533 | rc = inode_change_ok(inode, attrs); | 1641 | rc = inode_change_ok(inode, attrs); |
| @@ -1543,7 +1651,6 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
| 1543 | FreeXid(xid); | 1651 | FreeXid(xid); |
| 1544 | return -ENOMEM; | 1652 | return -ENOMEM; |
| 1545 | } | 1653 | } |
| 1546 | cifsInode = CIFS_I(inode); | ||
| 1547 | 1654 | ||
| 1548 | if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { | 1655 | if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { |
| 1549 | /* | 1656 | /* |
| @@ -1574,19 +1681,8 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
| 1574 | * CIFSACL support + proper Windows to Unix idmapping, we may be | 1681 | * CIFSACL support + proper Windows to Unix idmapping, we may be |
| 1575 | * able to support this in the future. | 1682 | * able to support this in the future. |
| 1576 | */ | 1683 | */ |
| 1577 | if (!pTcon->unix_ext && | 1684 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) |
| 1578 | !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { | ||
| 1579 | attrs->ia_valid &= ~(ATTR_UID | ATTR_GID); | 1685 | attrs->ia_valid &= ~(ATTR_UID | ATTR_GID); |
| 1580 | } else { | ||
| 1581 | if (attrs->ia_valid & ATTR_UID) { | ||
| 1582 | cFYI(1, ("UID changed to %d", attrs->ia_uid)); | ||
| 1583 | uid = attrs->ia_uid; | ||
| 1584 | } | ||
| 1585 | if (attrs->ia_valid & ATTR_GID) { | ||
| 1586 | cFYI(1, ("GID changed to %d", attrs->ia_gid)); | ||
| 1587 | gid = attrs->ia_gid; | ||
| 1588 | } | ||
| 1589 | } | ||
| 1590 | 1686 | ||
| 1591 | time_buf.Attributes = 0; | 1687 | time_buf.Attributes = 0; |
| 1592 | 1688 | ||
| @@ -1599,22 +1695,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
| 1599 | mode = attrs->ia_mode; | 1695 | mode = attrs->ia_mode; |
| 1600 | } | 1696 | } |
| 1601 | 1697 | ||
| 1602 | if ((pTcon->unix_ext) | 1698 | if (attrs->ia_valid & ATTR_MODE) { |
| 1603 | && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID))) { | ||
| 1604 | struct cifs_unix_set_info_args args = { | ||
| 1605 | .mode = mode, | ||
| 1606 | .uid = uid, | ||
| 1607 | .gid = gid, | ||
| 1608 | .ctime = NO_CHANGE_64, | ||
| 1609 | .atime = NO_CHANGE_64, | ||
| 1610 | .mtime = NO_CHANGE_64, | ||
| 1611 | .device = 0, | ||
| 1612 | }; | ||
| 1613 | rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, | ||
| 1614 | cifs_sb->local_nls, | ||
| 1615 | cifs_sb->mnt_cifs_flags & | ||
| 1616 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 1617 | } else if (attrs->ia_valid & ATTR_MODE) { | ||
| 1618 | rc = 0; | 1699 | rc = 0; |
| 1619 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 1700 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 1620 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) | 1701 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) |
