diff options
Diffstat (limited to 'fs/cifs/file.c')
| -rw-r--r-- | fs/cifs/file.c | 175 | 
1 files changed, 130 insertions, 45 deletions
| diff --git a/fs/cifs/file.c b/fs/cifs/file.c index bd2a028af833..d7d65a70678e 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -287,6 +287,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | |||
| 287 | struct inode *inode = cifs_file->dentry->d_inode; | 287 | struct inode *inode = cifs_file->dentry->d_inode; | 
| 288 | struct cifsTconInfo *tcon = tlink_tcon(cifs_file->tlink); | 288 | struct cifsTconInfo *tcon = tlink_tcon(cifs_file->tlink); | 
| 289 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | 289 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | 
| 290 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
| 290 | struct cifsLockInfo *li, *tmp; | 291 | struct cifsLockInfo *li, *tmp; | 
| 291 | 292 | ||
| 292 | spin_lock(&cifs_file_list_lock); | 293 | spin_lock(&cifs_file_list_lock); | 
| @@ -302,6 +303,13 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | |||
| 302 | if (list_empty(&cifsi->openFileList)) { | 303 | if (list_empty(&cifsi->openFileList)) { | 
| 303 | cFYI(1, "closing last open instance for inode %p", | 304 | cFYI(1, "closing last open instance for inode %p", | 
| 304 | cifs_file->dentry->d_inode); | 305 | cifs_file->dentry->d_inode); | 
| 306 | |||
| 307 | /* in strict cache mode we need invalidate mapping on the last | ||
| 308 | close because it may cause a error when we open this file | ||
| 309 | again and get at least level II oplock */ | ||
| 310 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) | ||
| 311 | CIFS_I(inode)->invalid_mapping = true; | ||
| 312 | |||
| 305 | cifs_set_oplock_level(cifsi, 0); | 313 | cifs_set_oplock_level(cifsi, 0); | 
| 306 | } | 314 | } | 
| 307 | spin_unlock(&cifs_file_list_lock); | 315 | spin_unlock(&cifs_file_list_lock); | 
| @@ -1520,27 +1528,47 @@ static int cifs_write_end(struct file *file, struct address_space *mapping, | |||
| 1520 | return rc; | 1528 | return rc; | 
| 1521 | } | 1529 | } | 
| 1522 | 1530 | ||
| 1523 | int cifs_fsync(struct file *file, int datasync) | 1531 | int cifs_strict_fsync(struct file *file, int datasync) | 
| 1524 | { | 1532 | { | 
| 1525 | int xid; | 1533 | int xid; | 
| 1526 | int rc = 0; | 1534 | int rc = 0; | 
| 1527 | struct cifsTconInfo *tcon; | 1535 | struct cifsTconInfo *tcon; | 
| 1528 | struct cifsFileInfo *smbfile = file->private_data; | 1536 | struct cifsFileInfo *smbfile = file->private_data; | 
| 1529 | struct inode *inode = file->f_path.dentry->d_inode; | 1537 | struct inode *inode = file->f_path.dentry->d_inode; | 
| 1538 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
| 1530 | 1539 | ||
| 1531 | xid = GetXid(); | 1540 | xid = GetXid(); | 
| 1532 | 1541 | ||
| 1533 | cFYI(1, "Sync file - name: %s datasync: 0x%x", | 1542 | cFYI(1, "Sync file - name: %s datasync: 0x%x", | 
| 1534 | file->f_path.dentry->d_name.name, datasync); | 1543 | file->f_path.dentry->d_name.name, datasync); | 
| 1535 | 1544 | ||
| 1536 | rc = filemap_write_and_wait(inode->i_mapping); | 1545 | if (!CIFS_I(inode)->clientCanCacheRead) | 
| 1537 | if (rc == 0) { | 1546 | cifs_invalidate_mapping(inode); | 
| 1538 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
| 1539 | 1547 | ||
| 1540 | tcon = tlink_tcon(smbfile->tlink); | 1548 | tcon = tlink_tcon(smbfile->tlink); | 
| 1541 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | 1549 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | 
| 1542 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | 1550 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | 
| 1543 | } | 1551 | |
| 1552 | FreeXid(xid); | ||
| 1553 | return rc; | ||
| 1554 | } | ||
| 1555 | |||
| 1556 | int cifs_fsync(struct file *file, int datasync) | ||
| 1557 | { | ||
| 1558 | int xid; | ||
| 1559 | int rc = 0; | ||
| 1560 | struct cifsTconInfo *tcon; | ||
| 1561 | struct cifsFileInfo *smbfile = file->private_data; | ||
| 1562 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | ||
| 1563 | |||
| 1564 | xid = GetXid(); | ||
| 1565 | |||
| 1566 | cFYI(1, "Sync file - name: %s datasync: 0x%x", | ||
| 1567 | file->f_path.dentry->d_name.name, datasync); | ||
| 1568 | |||
| 1569 | tcon = tlink_tcon(smbfile->tlink); | ||
| 1570 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | ||
| 1571 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | ||
| 1544 | 1572 | ||
| 1545 | FreeXid(xid); | 1573 | FreeXid(xid); | 
| 1546 | return rc; | 1574 | return rc; | 
| @@ -1591,42 +1619,42 @@ int cifs_flush(struct file *file, fl_owner_t id) | |||
| 1591 | return rc; | 1619 | return rc; | 
| 1592 | } | 1620 | } | 
| 1593 | 1621 | ||
| 1594 | ssize_t cifs_user_read(struct file *file, char __user *read_data, | 1622 | static ssize_t | 
| 1595 | size_t read_size, loff_t *poffset) | 1623 | cifs_iovec_read(struct file *file, const struct iovec *iov, | 
| 1624 | unsigned long nr_segs, loff_t *poffset) | ||
| 1596 | { | 1625 | { | 
| 1597 | int rc = -EACCES; | 1626 | int rc; | 
| 1598 | unsigned int bytes_read = 0; | 1627 | int xid; | 
| 1599 | unsigned int total_read = 0; | 1628 | unsigned int total_read, bytes_read = 0; | 
| 1600 | unsigned int current_read_size; | 1629 | size_t len, cur_len; | 
| 1630 | int iov_offset = 0; | ||
| 1601 | struct cifs_sb_info *cifs_sb; | 1631 | struct cifs_sb_info *cifs_sb; | 
| 1602 | struct cifsTconInfo *pTcon; | 1632 | struct cifsTconInfo *pTcon; | 
| 1603 | int xid; | ||
| 1604 | struct cifsFileInfo *open_file; | 1633 | struct cifsFileInfo *open_file; | 
| 1605 | char *smb_read_data; | ||
| 1606 | char __user *current_offset; | ||
| 1607 | struct smb_com_read_rsp *pSMBr; | 1634 | struct smb_com_read_rsp *pSMBr; | 
| 1635 | char *read_data; | ||
| 1636 | |||
| 1637 | if (!nr_segs) | ||
| 1638 | return 0; | ||
| 1639 | |||
| 1640 | len = iov_length(iov, nr_segs); | ||
| 1641 | if (!len) | ||
| 1642 | return 0; | ||
| 1608 | 1643 | ||
| 1609 | xid = GetXid(); | 1644 | xid = GetXid(); | 
| 1610 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 1645 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 
| 1611 | 1646 | ||
| 1612 | if (file->private_data == NULL) { | ||
| 1613 | rc = -EBADF; | ||
| 1614 | FreeXid(xid); | ||
| 1615 | return rc; | ||
| 1616 | } | ||
| 1617 | open_file = file->private_data; | 1647 | open_file = file->private_data; | 
| 1618 | pTcon = tlink_tcon(open_file->tlink); | 1648 | pTcon = tlink_tcon(open_file->tlink); | 
| 1619 | 1649 | ||
| 1620 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | 1650 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | 
| 1621 | cFYI(1, "attempting read on write only file instance"); | 1651 | cFYI(1, "attempting read on write only file instance"); | 
| 1622 | 1652 | ||
| 1623 | for (total_read = 0, current_offset = read_data; | 1653 | for (total_read = 0; total_read < len; total_read += bytes_read) { | 
| 1624 | read_size > total_read; | 1654 | cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize); | 
| 1625 | total_read += bytes_read, current_offset += bytes_read) { | ||
| 1626 | current_read_size = min_t(const int, read_size - total_read, | ||
| 1627 | cifs_sb->rsize); | ||
| 1628 | rc = -EAGAIN; | 1655 | rc = -EAGAIN; | 
| 1629 | smb_read_data = NULL; | 1656 | read_data = NULL; | 
| 1657 | |||
| 1630 | while (rc == -EAGAIN) { | 1658 | while (rc == -EAGAIN) { | 
| 1631 | int buf_type = CIFS_NO_BUFFER; | 1659 | int buf_type = CIFS_NO_BUFFER; | 
| 1632 | if (open_file->invalidHandle) { | 1660 | if (open_file->invalidHandle) { | 
| @@ -1634,27 +1662,25 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
| 1634 | if (rc != 0) | 1662 | if (rc != 0) | 
| 1635 | break; | 1663 | break; | 
| 1636 | } | 1664 | } | 
| 1637 | rc = CIFSSMBRead(xid, pTcon, | 1665 | rc = CIFSSMBRead(xid, pTcon, open_file->netfid, | 
| 1638 | open_file->netfid, | 1666 | cur_len, *poffset, &bytes_read, | 
| 1639 | current_read_size, *poffset, | 1667 | &read_data, &buf_type); | 
| 1640 | &bytes_read, &smb_read_data, | 1668 | pSMBr = (struct smb_com_read_rsp *)read_data; | 
| 1641 | &buf_type); | 1669 | if (read_data) { | 
| 1642 | pSMBr = (struct smb_com_read_rsp *)smb_read_data; | 1670 | char *data_offset = read_data + 4 + | 
| 1643 | if (smb_read_data) { | 1671 | le16_to_cpu(pSMBr->DataOffset); | 
| 1644 | if (copy_to_user(current_offset, | 1672 | if (memcpy_toiovecend(iov, data_offset, | 
| 1645 | smb_read_data + | 1673 | iov_offset, bytes_read)) | 
| 1646 | 4 /* RFC1001 length field */ + | ||
| 1647 | le16_to_cpu(pSMBr->DataOffset), | ||
| 1648 | bytes_read)) | ||
| 1649 | rc = -EFAULT; | 1674 | rc = -EFAULT; | 
| 1650 | |||
| 1651 | if (buf_type == CIFS_SMALL_BUFFER) | 1675 | if (buf_type == CIFS_SMALL_BUFFER) | 
| 1652 | cifs_small_buf_release(smb_read_data); | 1676 | cifs_small_buf_release(read_data); | 
| 1653 | else if (buf_type == CIFS_LARGE_BUFFER) | 1677 | else if (buf_type == CIFS_LARGE_BUFFER) | 
| 1654 | cifs_buf_release(smb_read_data); | 1678 | cifs_buf_release(read_data); | 
| 1655 | smb_read_data = NULL; | 1679 | read_data = NULL; | 
| 1680 | iov_offset += bytes_read; | ||
| 1656 | } | 1681 | } | 
| 1657 | } | 1682 | } | 
| 1683 | |||
| 1658 | if (rc || (bytes_read == 0)) { | 1684 | if (rc || (bytes_read == 0)) { | 
| 1659 | if (total_read) { | 1685 | if (total_read) { | 
| 1660 | break; | 1686 | break; | 
| @@ -1667,13 +1693,57 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
| 1667 | *poffset += bytes_read; | 1693 | *poffset += bytes_read; | 
| 1668 | } | 1694 | } | 
| 1669 | } | 1695 | } | 
| 1696 | |||
| 1670 | FreeXid(xid); | 1697 | FreeXid(xid); | 
| 1671 | return total_read; | 1698 | return total_read; | 
| 1672 | } | 1699 | } | 
| 1673 | 1700 | ||
| 1701 | ssize_t cifs_user_read(struct file *file, char __user *read_data, | ||
| 1702 | size_t read_size, loff_t *poffset) | ||
| 1703 | { | ||
| 1704 | struct iovec iov; | ||
| 1705 | iov.iov_base = read_data; | ||
| 1706 | iov.iov_len = read_size; | ||
| 1707 | |||
| 1708 | return cifs_iovec_read(file, &iov, 1, poffset); | ||
| 1709 | } | ||
| 1710 | |||
| 1711 | static ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, | ||
| 1712 | unsigned long nr_segs, loff_t pos) | ||
| 1713 | { | ||
| 1714 | ssize_t read; | ||
| 1715 | |||
| 1716 | read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos); | ||
| 1717 | if (read > 0) | ||
| 1718 | iocb->ki_pos = pos; | ||
| 1719 | |||
| 1720 | return read; | ||
| 1721 | } | ||
| 1722 | |||
| 1723 | ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, | ||
| 1724 | unsigned long nr_segs, loff_t pos) | ||
| 1725 | { | ||
| 1726 | struct inode *inode; | ||
| 1727 | |||
| 1728 | inode = iocb->ki_filp->f_path.dentry->d_inode; | ||
| 1729 | |||
| 1730 | if (CIFS_I(inode)->clientCanCacheRead) | ||
| 1731 | return generic_file_aio_read(iocb, iov, nr_segs, pos); | ||
| 1732 | |||
| 1733 | /* | ||
| 1734 | * In strict cache mode we need to read from the server all the time | ||
| 1735 | * if we don't have level II oplock because the server can delay mtime | ||
| 1736 | * change - so we can't make a decision about inode invalidating. | ||
| 1737 | * And we can also fail with pagereading if there are mandatory locks | ||
| 1738 | * on pages affected by this read but not on the region from pos to | ||
| 1739 | * pos+len-1. | ||
| 1740 | */ | ||
| 1741 | |||
| 1742 | return cifs_user_readv(iocb, iov, nr_segs, pos); | ||
| 1743 | } | ||
| 1674 | 1744 | ||
| 1675 | static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | 1745 | static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | 
| 1676 | loff_t *poffset) | 1746 | loff_t *poffset) | 
| 1677 | { | 1747 | { | 
| 1678 | int rc = -EACCES; | 1748 | int rc = -EACCES; | 
| 1679 | unsigned int bytes_read = 0; | 1749 | unsigned int bytes_read = 0; | 
| @@ -1741,6 +1811,21 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
| 1741 | return total_read; | 1811 | return total_read; | 
| 1742 | } | 1812 | } | 
| 1743 | 1813 | ||
| 1814 | int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) | ||
| 1815 | { | ||
| 1816 | int rc, xid; | ||
| 1817 | struct inode *inode = file->f_path.dentry->d_inode; | ||
| 1818 | |||
| 1819 | xid = GetXid(); | ||
| 1820 | |||
| 1821 | if (!CIFS_I(inode)->clientCanCacheRead) | ||
| 1822 | cifs_invalidate_mapping(inode); | ||
| 1823 | |||
| 1824 | rc = generic_file_mmap(file, vma); | ||
| 1825 | FreeXid(xid); | ||
| 1826 | return rc; | ||
| 1827 | } | ||
| 1828 | |||
| 1744 | int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) | 1829 | int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) | 
| 1745 | { | 1830 | { | 
| 1746 | int rc, xid; | 1831 | int rc, xid; | 
