diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 289 |
1 files changed, 185 insertions, 104 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index d843631c028d..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); |
@@ -726,12 +734,12 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
726 | 734 | ||
727 | /* BB we could chain these into one lock request BB */ | 735 | /* BB we could chain these into one lock request BB */ |
728 | rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start, | 736 | rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start, |
729 | 0, 1, lockType, 0 /* wait flag */ ); | 737 | 0, 1, lockType, 0 /* wait flag */, 0); |
730 | if (rc == 0) { | 738 | if (rc == 0) { |
731 | rc = CIFSSMBLock(xid, tcon, netfid, length, | 739 | rc = CIFSSMBLock(xid, tcon, netfid, length, |
732 | pfLock->fl_start, 1 /* numUnlock */ , | 740 | pfLock->fl_start, 1 /* numUnlock */ , |
733 | 0 /* numLock */ , lockType, | 741 | 0 /* numLock */ , lockType, |
734 | 0 /* wait flag */ ); | 742 | 0 /* wait flag */, 0); |
735 | pfLock->fl_type = F_UNLCK; | 743 | pfLock->fl_type = F_UNLCK; |
736 | if (rc != 0) | 744 | if (rc != 0) |
737 | cERROR(1, "Error unlocking previously locked " | 745 | cERROR(1, "Error unlocking previously locked " |
@@ -748,13 +756,13 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
748 | rc = CIFSSMBLock(xid, tcon, netfid, length, | 756 | rc = CIFSSMBLock(xid, tcon, netfid, length, |
749 | pfLock->fl_start, 0, 1, | 757 | pfLock->fl_start, 0, 1, |
750 | lockType | LOCKING_ANDX_SHARED_LOCK, | 758 | lockType | LOCKING_ANDX_SHARED_LOCK, |
751 | 0 /* wait flag */); | 759 | 0 /* wait flag */, 0); |
752 | if (rc == 0) { | 760 | if (rc == 0) { |
753 | rc = CIFSSMBLock(xid, tcon, netfid, | 761 | rc = CIFSSMBLock(xid, tcon, netfid, |
754 | length, pfLock->fl_start, 1, 0, | 762 | length, pfLock->fl_start, 1, 0, |
755 | lockType | | 763 | lockType | |
756 | LOCKING_ANDX_SHARED_LOCK, | 764 | LOCKING_ANDX_SHARED_LOCK, |
757 | 0 /* wait flag */); | 765 | 0 /* wait flag */, 0); |
758 | pfLock->fl_type = F_RDLCK; | 766 | pfLock->fl_type = F_RDLCK; |
759 | if (rc != 0) | 767 | if (rc != 0) |
760 | cERROR(1, "Error unlocking " | 768 | cERROR(1, "Error unlocking " |
@@ -797,8 +805,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
797 | 805 | ||
798 | if (numLock) { | 806 | if (numLock) { |
799 | rc = CIFSSMBLock(xid, tcon, netfid, length, | 807 | rc = CIFSSMBLock(xid, tcon, netfid, length, |
800 | pfLock->fl_start, | 808 | pfLock->fl_start, 0, numLock, lockType, |
801 | 0, numLock, lockType, wait_flag); | 809 | wait_flag, 0); |
802 | 810 | ||
803 | if (rc == 0) { | 811 | if (rc == 0) { |
804 | /* For Windows locks we must store them. */ | 812 | /* For Windows locks we must store them. */ |
@@ -818,9 +826,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
818 | (pfLock->fl_start + length) >= | 826 | (pfLock->fl_start + length) >= |
819 | (li->offset + li->length)) { | 827 | (li->offset + li->length)) { |
820 | stored_rc = CIFSSMBLock(xid, tcon, | 828 | stored_rc = CIFSSMBLock(xid, tcon, |
821 | netfid, | 829 | netfid, li->length, |
822 | li->length, li->offset, | 830 | li->offset, 1, 0, |
823 | 1, 0, li->type, false); | 831 | li->type, false, 0); |
824 | if (stored_rc) | 832 | if (stored_rc) |
825 | rc = stored_rc; | 833 | rc = stored_rc; |
826 | else { | 834 | else { |
@@ -839,29 +847,6 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
839 | return rc; | 847 | return rc; |
840 | } | 848 | } |
841 | 849 | ||
842 | /* | ||
843 | * Set the timeout on write requests past EOF. For some servers (Windows) | ||
844 | * these calls can be very long. | ||
845 | * | ||
846 | * If we're writing >10M past the EOF we give a 180s timeout. Anything less | ||
847 | * than that gets a 45s timeout. Writes not past EOF get 15s timeouts. | ||
848 | * The 10M cutoff is totally arbitrary. A better scheme for this would be | ||
849 | * welcome if someone wants to suggest one. | ||
850 | * | ||
851 | * We may be able to do a better job with this if there were some way to | ||
852 | * declare that a file should be sparse. | ||
853 | */ | ||
854 | static int | ||
855 | cifs_write_timeout(struct cifsInodeInfo *cifsi, loff_t offset) | ||
856 | { | ||
857 | if (offset <= cifsi->server_eof) | ||
858 | return CIFS_STD_OP; | ||
859 | else if (offset > (cifsi->server_eof + (10 * 1024 * 1024))) | ||
860 | return CIFS_VLONG_OP; | ||
861 | else | ||
862 | return CIFS_LONG_OP; | ||
863 | } | ||
864 | |||
865 | /* update the file size (if needed) after a write */ | 850 | /* update the file size (if needed) after a write */ |
866 | static void | 851 | static void |
867 | cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, | 852 | cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, |
@@ -882,7 +867,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
882 | unsigned int total_written; | 867 | unsigned int total_written; |
883 | struct cifs_sb_info *cifs_sb; | 868 | struct cifs_sb_info *cifs_sb; |
884 | struct cifsTconInfo *pTcon; | 869 | struct cifsTconInfo *pTcon; |
885 | int xid, long_op; | 870 | int xid; |
886 | struct cifsFileInfo *open_file; | 871 | struct cifsFileInfo *open_file; |
887 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | 872 | struct cifsInodeInfo *cifsi = CIFS_I(inode); |
888 | 873 | ||
@@ -903,7 +888,6 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
903 | 888 | ||
904 | xid = GetXid(); | 889 | xid = GetXid(); |
905 | 890 | ||
906 | long_op = cifs_write_timeout(cifsi, *poffset); | ||
907 | for (total_written = 0; write_size > total_written; | 891 | for (total_written = 0; write_size > total_written; |
908 | total_written += bytes_written) { | 892 | total_written += bytes_written) { |
909 | rc = -EAGAIN; | 893 | rc = -EAGAIN; |
@@ -931,7 +915,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
931 | min_t(const int, cifs_sb->wsize, | 915 | min_t(const int, cifs_sb->wsize, |
932 | write_size - total_written), | 916 | write_size - total_written), |
933 | *poffset, &bytes_written, | 917 | *poffset, &bytes_written, |
934 | NULL, write_data + total_written, long_op); | 918 | NULL, write_data + total_written, 0); |
935 | } | 919 | } |
936 | if (rc || (bytes_written == 0)) { | 920 | if (rc || (bytes_written == 0)) { |
937 | if (total_written) | 921 | if (total_written) |
@@ -944,8 +928,6 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
944 | cifs_update_eof(cifsi, *poffset, bytes_written); | 928 | cifs_update_eof(cifsi, *poffset, bytes_written); |
945 | *poffset += bytes_written; | 929 | *poffset += bytes_written; |
946 | } | 930 | } |
947 | long_op = CIFS_STD_OP; /* subsequent writes fast - | ||
948 | 15 seconds is plenty */ | ||
949 | } | 931 | } |
950 | 932 | ||
951 | cifs_stats_bytes_written(pTcon, total_written); | 933 | cifs_stats_bytes_written(pTcon, total_written); |
@@ -974,7 +956,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
974 | unsigned int total_written; | 956 | unsigned int total_written; |
975 | struct cifs_sb_info *cifs_sb; | 957 | struct cifs_sb_info *cifs_sb; |
976 | struct cifsTconInfo *pTcon; | 958 | struct cifsTconInfo *pTcon; |
977 | int xid, long_op; | 959 | int xid; |
978 | struct dentry *dentry = open_file->dentry; | 960 | struct dentry *dentry = open_file->dentry; |
979 | struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode); | 961 | struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode); |
980 | 962 | ||
@@ -987,7 +969,6 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
987 | 969 | ||
988 | xid = GetXid(); | 970 | xid = GetXid(); |
989 | 971 | ||
990 | long_op = cifs_write_timeout(cifsi, *poffset); | ||
991 | for (total_written = 0; write_size > total_written; | 972 | for (total_written = 0; write_size > total_written; |
992 | total_written += bytes_written) { | 973 | total_written += bytes_written) { |
993 | rc = -EAGAIN; | 974 | rc = -EAGAIN; |
@@ -1017,7 +998,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
1017 | rc = CIFSSMBWrite2(xid, pTcon, | 998 | rc = CIFSSMBWrite2(xid, pTcon, |
1018 | open_file->netfid, len, | 999 | open_file->netfid, len, |
1019 | *poffset, &bytes_written, | 1000 | *poffset, &bytes_written, |
1020 | iov, 1, long_op); | 1001 | iov, 1, 0); |
1021 | } else | 1002 | } else |
1022 | rc = CIFSSMBWrite(xid, pTcon, | 1003 | rc = CIFSSMBWrite(xid, pTcon, |
1023 | open_file->netfid, | 1004 | open_file->netfid, |
@@ -1025,7 +1006,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
1025 | write_size - total_written), | 1006 | write_size - total_written), |
1026 | *poffset, &bytes_written, | 1007 | *poffset, &bytes_written, |
1027 | write_data + total_written, | 1008 | write_data + total_written, |
1028 | NULL, long_op); | 1009 | NULL, 0); |
1029 | } | 1010 | } |
1030 | if (rc || (bytes_written == 0)) { | 1011 | if (rc || (bytes_written == 0)) { |
1031 | if (total_written) | 1012 | if (total_written) |
@@ -1038,8 +1019,6 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
1038 | cifs_update_eof(cifsi, *poffset, bytes_written); | 1019 | cifs_update_eof(cifsi, *poffset, bytes_written); |
1039 | *poffset += bytes_written; | 1020 | *poffset += bytes_written; |
1040 | } | 1021 | } |
1041 | long_op = CIFS_STD_OP; /* subsequent writes fast - | ||
1042 | 15 seconds is plenty */ | ||
1043 | } | 1022 | } |
1044 | 1023 | ||
1045 | cifs_stats_bytes_written(pTcon, total_written); | 1024 | cifs_stats_bytes_written(pTcon, total_written); |
@@ -1239,7 +1218,7 @@ static int cifs_writepages(struct address_space *mapping, | |||
1239 | struct pagevec pvec; | 1218 | struct pagevec pvec; |
1240 | int rc = 0; | 1219 | int rc = 0; |
1241 | int scanned = 0; | 1220 | int scanned = 0; |
1242 | int xid, long_op; | 1221 | int xid; |
1243 | 1222 | ||
1244 | cifs_sb = CIFS_SB(mapping->host->i_sb); | 1223 | cifs_sb = CIFS_SB(mapping->host->i_sb); |
1245 | 1224 | ||
@@ -1377,43 +1356,67 @@ retry: | |||
1377 | break; | 1356 | break; |
1378 | } | 1357 | } |
1379 | if (n_iov) { | 1358 | if (n_iov) { |
1359 | retry_write: | ||
1380 | open_file = find_writable_file(CIFS_I(mapping->host), | 1360 | open_file = find_writable_file(CIFS_I(mapping->host), |
1381 | false); | 1361 | false); |
1382 | if (!open_file) { | 1362 | if (!open_file) { |
1383 | cERROR(1, "No writable handles for inode"); | 1363 | cERROR(1, "No writable handles for inode"); |
1384 | rc = -EBADF; | 1364 | rc = -EBADF; |
1385 | } else { | 1365 | } else { |
1386 | long_op = cifs_write_timeout(cifsi, offset); | ||
1387 | rc = CIFSSMBWrite2(xid, tcon, open_file->netfid, | 1366 | rc = CIFSSMBWrite2(xid, tcon, open_file->netfid, |
1388 | bytes_to_write, offset, | 1367 | bytes_to_write, offset, |
1389 | &bytes_written, iov, n_iov, | 1368 | &bytes_written, iov, n_iov, |
1390 | long_op); | 1369 | 0); |
1391 | cifsFileInfo_put(open_file); | 1370 | cifsFileInfo_put(open_file); |
1392 | cifs_update_eof(cifsi, offset, bytes_written); | ||
1393 | } | 1371 | } |
1394 | 1372 | ||
1395 | if (rc || bytes_written < bytes_to_write) { | 1373 | cFYI(1, "Write2 rc=%d, wrote=%u", rc, bytes_written); |
1396 | cERROR(1, "Write2 ret %d, wrote %d", | 1374 | |
1397 | rc, bytes_written); | 1375 | /* |
1398 | mapping_set_error(mapping, rc); | 1376 | * For now, treat a short write as if nothing got |
1399 | } else { | 1377 | * written. A zero length write however indicates |
1378 | * ENOSPC or EFBIG. We have no way to know which | ||
1379 | * though, so call it ENOSPC for now. EFBIG would | ||
1380 | * get translated to AS_EIO anyway. | ||
1381 | * | ||
1382 | * FIXME: make it take into account the data that did | ||
1383 | * get written | ||
1384 | */ | ||
1385 | if (rc == 0) { | ||
1386 | if (bytes_written == 0) | ||
1387 | rc = -ENOSPC; | ||
1388 | else if (bytes_written < bytes_to_write) | ||
1389 | rc = -EAGAIN; | ||
1390 | } | ||
1391 | |||
1392 | /* retry on data-integrity flush */ | ||
1393 | if (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN) | ||
1394 | goto retry_write; | ||
1395 | |||
1396 | /* fix the stats and EOF */ | ||
1397 | if (bytes_written > 0) { | ||
1400 | cifs_stats_bytes_written(tcon, bytes_written); | 1398 | cifs_stats_bytes_written(tcon, bytes_written); |
1399 | cifs_update_eof(cifsi, offset, bytes_written); | ||
1401 | } | 1400 | } |
1402 | 1401 | ||
1403 | for (i = 0; i < n_iov; i++) { | 1402 | for (i = 0; i < n_iov; i++) { |
1404 | page = pvec.pages[first + i]; | 1403 | page = pvec.pages[first + i]; |
1405 | /* Should we also set page error on | 1404 | /* on retryable write error, redirty page */ |
1406 | success rc but too little data written? */ | 1405 | if (rc == -EAGAIN) |
1407 | /* BB investigate retry logic on temporary | 1406 | redirty_page_for_writepage(wbc, page); |
1408 | server crash cases and how recovery works | 1407 | else if (rc != 0) |
1409 | when page marked as error */ | ||
1410 | if (rc) | ||
1411 | SetPageError(page); | 1408 | SetPageError(page); |
1412 | kunmap(page); | 1409 | kunmap(page); |
1413 | unlock_page(page); | 1410 | unlock_page(page); |
1414 | end_page_writeback(page); | 1411 | end_page_writeback(page); |
1415 | page_cache_release(page); | 1412 | page_cache_release(page); |
1416 | } | 1413 | } |
1414 | |||
1415 | if (rc != -EAGAIN) | ||
1416 | mapping_set_error(mapping, rc); | ||
1417 | else | ||
1418 | rc = 0; | ||
1419 | |||
1417 | if ((wbc->nr_to_write -= n_iov) <= 0) | 1420 | if ((wbc->nr_to_write -= n_iov) <= 0) |
1418 | done = 1; | 1421 | done = 1; |
1419 | index = next; | 1422 | index = next; |
@@ -1525,27 +1528,47 @@ static int cifs_write_end(struct file *file, struct address_space *mapping, | |||
1525 | return rc; | 1528 | return rc; |
1526 | } | 1529 | } |
1527 | 1530 | ||
1528 | int cifs_fsync(struct file *file, int datasync) | 1531 | int cifs_strict_fsync(struct file *file, int datasync) |
1529 | { | 1532 | { |
1530 | int xid; | 1533 | int xid; |
1531 | int rc = 0; | 1534 | int rc = 0; |
1532 | struct cifsTconInfo *tcon; | 1535 | struct cifsTconInfo *tcon; |
1533 | struct cifsFileInfo *smbfile = file->private_data; | 1536 | struct cifsFileInfo *smbfile = file->private_data; |
1534 | 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); | ||
1535 | 1539 | ||
1536 | xid = GetXid(); | 1540 | xid = GetXid(); |
1537 | 1541 | ||
1538 | cFYI(1, "Sync file - name: %s datasync: 0x%x", | 1542 | cFYI(1, "Sync file - name: %s datasync: 0x%x", |
1539 | file->f_path.dentry->d_name.name, datasync); | 1543 | file->f_path.dentry->d_name.name, datasync); |
1540 | 1544 | ||
1541 | rc = filemap_write_and_wait(inode->i_mapping); | 1545 | if (!CIFS_I(inode)->clientCanCacheRead) |
1542 | if (rc == 0) { | 1546 | cifs_invalidate_mapping(inode); |
1543 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
1544 | 1547 | ||
1545 | tcon = tlink_tcon(smbfile->tlink); | 1548 | tcon = tlink_tcon(smbfile->tlink); |
1546 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | 1549 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) |
1547 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | 1550 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); |
1548 | } | 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); | ||
1549 | 1572 | ||
1550 | FreeXid(xid); | 1573 | FreeXid(xid); |
1551 | return rc; | 1574 | return rc; |
@@ -1596,42 +1619,42 @@ int cifs_flush(struct file *file, fl_owner_t id) | |||
1596 | return rc; | 1619 | return rc; |
1597 | } | 1620 | } |
1598 | 1621 | ||
1599 | ssize_t cifs_user_read(struct file *file, char __user *read_data, | 1622 | static ssize_t |
1600 | 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) | ||
1601 | { | 1625 | { |
1602 | int rc = -EACCES; | 1626 | int rc; |
1603 | unsigned int bytes_read = 0; | 1627 | int xid; |
1604 | unsigned int total_read = 0; | 1628 | unsigned int total_read, bytes_read = 0; |
1605 | unsigned int current_read_size; | 1629 | size_t len, cur_len; |
1630 | int iov_offset = 0; | ||
1606 | struct cifs_sb_info *cifs_sb; | 1631 | struct cifs_sb_info *cifs_sb; |
1607 | struct cifsTconInfo *pTcon; | 1632 | struct cifsTconInfo *pTcon; |
1608 | int xid; | ||
1609 | struct cifsFileInfo *open_file; | 1633 | struct cifsFileInfo *open_file; |
1610 | char *smb_read_data; | ||
1611 | char __user *current_offset; | ||
1612 | 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; | ||
1613 | 1643 | ||
1614 | xid = GetXid(); | 1644 | xid = GetXid(); |
1615 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 1645 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
1616 | 1646 | ||
1617 | if (file->private_data == NULL) { | ||
1618 | rc = -EBADF; | ||
1619 | FreeXid(xid); | ||
1620 | return rc; | ||
1621 | } | ||
1622 | open_file = file->private_data; | 1647 | open_file = file->private_data; |
1623 | pTcon = tlink_tcon(open_file->tlink); | 1648 | pTcon = tlink_tcon(open_file->tlink); |
1624 | 1649 | ||
1625 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | 1650 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) |
1626 | cFYI(1, "attempting read on write only file instance"); | 1651 | cFYI(1, "attempting read on write only file instance"); |
1627 | 1652 | ||
1628 | for (total_read = 0, current_offset = read_data; | 1653 | for (total_read = 0; total_read < len; total_read += bytes_read) { |
1629 | read_size > total_read; | 1654 | cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize); |
1630 | total_read += bytes_read, current_offset += bytes_read) { | ||
1631 | current_read_size = min_t(const int, read_size - total_read, | ||
1632 | cifs_sb->rsize); | ||
1633 | rc = -EAGAIN; | 1655 | rc = -EAGAIN; |
1634 | smb_read_data = NULL; | 1656 | read_data = NULL; |
1657 | |||
1635 | while (rc == -EAGAIN) { | 1658 | while (rc == -EAGAIN) { |
1636 | int buf_type = CIFS_NO_BUFFER; | 1659 | int buf_type = CIFS_NO_BUFFER; |
1637 | if (open_file->invalidHandle) { | 1660 | if (open_file->invalidHandle) { |
@@ -1639,27 +1662,25 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
1639 | if (rc != 0) | 1662 | if (rc != 0) |
1640 | break; | 1663 | break; |
1641 | } | 1664 | } |
1642 | rc = CIFSSMBRead(xid, pTcon, | 1665 | rc = CIFSSMBRead(xid, pTcon, open_file->netfid, |
1643 | open_file->netfid, | 1666 | cur_len, *poffset, &bytes_read, |
1644 | current_read_size, *poffset, | 1667 | &read_data, &buf_type); |
1645 | &bytes_read, &smb_read_data, | 1668 | pSMBr = (struct smb_com_read_rsp *)read_data; |
1646 | &buf_type); | 1669 | if (read_data) { |
1647 | pSMBr = (struct smb_com_read_rsp *)smb_read_data; | 1670 | char *data_offset = read_data + 4 + |
1648 | if (smb_read_data) { | 1671 | le16_to_cpu(pSMBr->DataOffset); |
1649 | if (copy_to_user(current_offset, | 1672 | if (memcpy_toiovecend(iov, data_offset, |
1650 | smb_read_data + | 1673 | iov_offset, bytes_read)) |
1651 | 4 /* RFC1001 length field */ + | ||
1652 | le16_to_cpu(pSMBr->DataOffset), | ||
1653 | bytes_read)) | ||
1654 | rc = -EFAULT; | 1674 | rc = -EFAULT; |
1655 | |||
1656 | if (buf_type == CIFS_SMALL_BUFFER) | 1675 | if (buf_type == CIFS_SMALL_BUFFER) |
1657 | cifs_small_buf_release(smb_read_data); | 1676 | cifs_small_buf_release(read_data); |
1658 | else if (buf_type == CIFS_LARGE_BUFFER) | 1677 | else if (buf_type == CIFS_LARGE_BUFFER) |
1659 | cifs_buf_release(smb_read_data); | 1678 | cifs_buf_release(read_data); |
1660 | smb_read_data = NULL; | 1679 | read_data = NULL; |
1680 | iov_offset += bytes_read; | ||
1661 | } | 1681 | } |
1662 | } | 1682 | } |
1683 | |||
1663 | if (rc || (bytes_read == 0)) { | 1684 | if (rc || (bytes_read == 0)) { |
1664 | if (total_read) { | 1685 | if (total_read) { |
1665 | break; | 1686 | break; |
@@ -1672,13 +1693,57 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
1672 | *poffset += bytes_read; | 1693 | *poffset += bytes_read; |
1673 | } | 1694 | } |
1674 | } | 1695 | } |
1696 | |||
1675 | FreeXid(xid); | 1697 | FreeXid(xid); |
1676 | return total_read; | 1698 | return total_read; |
1677 | } | 1699 | } |
1678 | 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 | } | ||
1679 | 1744 | ||
1680 | 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, |
1681 | loff_t *poffset) | 1746 | loff_t *poffset) |
1682 | { | 1747 | { |
1683 | int rc = -EACCES; | 1748 | int rc = -EACCES; |
1684 | unsigned int bytes_read = 0; | 1749 | unsigned int bytes_read = 0; |
@@ -1746,6 +1811,21 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
1746 | return total_read; | 1811 | return total_read; |
1747 | } | 1812 | } |
1748 | 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 | |||
1749 | 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) |
1750 | { | 1830 | { |
1751 | int rc, xid; | 1831 | int rc, xid; |
@@ -2192,7 +2272,8 @@ void cifs_oplock_break(struct work_struct *work) | |||
2192 | */ | 2272 | */ |
2193 | if (!cfile->oplock_break_cancelled) { | 2273 | if (!cfile->oplock_break_cancelled) { |
2194 | rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0, | 2274 | rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0, |
2195 | 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false); | 2275 | 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false, |
2276 | cinode->clientCanCacheRead ? 1 : 0); | ||
2196 | cFYI(1, "Oplock release rc = %d", rc); | 2277 | cFYI(1, "Oplock release rc = %d", rc); |
2197 | } | 2278 | } |
2198 | 2279 | ||