diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 496 |
1 files changed, 387 insertions, 109 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index d843631c028d..e964b1cd5dd0 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); |
@@ -338,7 +346,6 @@ int cifs_open(struct inode *inode, struct file *file) | |||
338 | struct cifsTconInfo *tcon; | 346 | struct cifsTconInfo *tcon; |
339 | struct tcon_link *tlink; | 347 | struct tcon_link *tlink; |
340 | struct cifsFileInfo *pCifsFile = NULL; | 348 | struct cifsFileInfo *pCifsFile = NULL; |
341 | struct cifsInodeInfo *pCifsInode; | ||
342 | char *full_path = NULL; | 349 | char *full_path = NULL; |
343 | bool posix_open_ok = false; | 350 | bool posix_open_ok = false; |
344 | __u16 netfid; | 351 | __u16 netfid; |
@@ -353,8 +360,6 @@ int cifs_open(struct inode *inode, struct file *file) | |||
353 | } | 360 | } |
354 | tcon = tlink_tcon(tlink); | 361 | tcon = tlink_tcon(tlink); |
355 | 362 | ||
356 | pCifsInode = CIFS_I(file->f_path.dentry->d_inode); | ||
357 | |||
358 | full_path = build_path_from_dentry(file->f_path.dentry); | 363 | full_path = build_path_from_dentry(file->f_path.dentry); |
359 | if (full_path == NULL) { | 364 | if (full_path == NULL) { |
360 | rc = -ENOMEM; | 365 | rc = -ENOMEM; |
@@ -726,12 +731,12 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
726 | 731 | ||
727 | /* BB we could chain these into one lock request BB */ | 732 | /* BB we could chain these into one lock request BB */ |
728 | rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start, | 733 | rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start, |
729 | 0, 1, lockType, 0 /* wait flag */ ); | 734 | 0, 1, lockType, 0 /* wait flag */, 0); |
730 | if (rc == 0) { | 735 | if (rc == 0) { |
731 | rc = CIFSSMBLock(xid, tcon, netfid, length, | 736 | rc = CIFSSMBLock(xid, tcon, netfid, length, |
732 | pfLock->fl_start, 1 /* numUnlock */ , | 737 | pfLock->fl_start, 1 /* numUnlock */ , |
733 | 0 /* numLock */ , lockType, | 738 | 0 /* numLock */ , lockType, |
734 | 0 /* wait flag */ ); | 739 | 0 /* wait flag */, 0); |
735 | pfLock->fl_type = F_UNLCK; | 740 | pfLock->fl_type = F_UNLCK; |
736 | if (rc != 0) | 741 | if (rc != 0) |
737 | cERROR(1, "Error unlocking previously locked " | 742 | cERROR(1, "Error unlocking previously locked " |
@@ -748,13 +753,13 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
748 | rc = CIFSSMBLock(xid, tcon, netfid, length, | 753 | rc = CIFSSMBLock(xid, tcon, netfid, length, |
749 | pfLock->fl_start, 0, 1, | 754 | pfLock->fl_start, 0, 1, |
750 | lockType | LOCKING_ANDX_SHARED_LOCK, | 755 | lockType | LOCKING_ANDX_SHARED_LOCK, |
751 | 0 /* wait flag */); | 756 | 0 /* wait flag */, 0); |
752 | if (rc == 0) { | 757 | if (rc == 0) { |
753 | rc = CIFSSMBLock(xid, tcon, netfid, | 758 | rc = CIFSSMBLock(xid, tcon, netfid, |
754 | length, pfLock->fl_start, 1, 0, | 759 | length, pfLock->fl_start, 1, 0, |
755 | lockType | | 760 | lockType | |
756 | LOCKING_ANDX_SHARED_LOCK, | 761 | LOCKING_ANDX_SHARED_LOCK, |
757 | 0 /* wait flag */); | 762 | 0 /* wait flag */, 0); |
758 | pfLock->fl_type = F_RDLCK; | 763 | pfLock->fl_type = F_RDLCK; |
759 | if (rc != 0) | 764 | if (rc != 0) |
760 | cERROR(1, "Error unlocking " | 765 | cERROR(1, "Error unlocking " |
@@ -797,8 +802,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
797 | 802 | ||
798 | if (numLock) { | 803 | if (numLock) { |
799 | rc = CIFSSMBLock(xid, tcon, netfid, length, | 804 | rc = CIFSSMBLock(xid, tcon, netfid, length, |
800 | pfLock->fl_start, | 805 | pfLock->fl_start, 0, numLock, lockType, |
801 | 0, numLock, lockType, wait_flag); | 806 | wait_flag, 0); |
802 | 807 | ||
803 | if (rc == 0) { | 808 | if (rc == 0) { |
804 | /* For Windows locks we must store them. */ | 809 | /* For Windows locks we must store them. */ |
@@ -818,9 +823,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
818 | (pfLock->fl_start + length) >= | 823 | (pfLock->fl_start + length) >= |
819 | (li->offset + li->length)) { | 824 | (li->offset + li->length)) { |
820 | stored_rc = CIFSSMBLock(xid, tcon, | 825 | stored_rc = CIFSSMBLock(xid, tcon, |
821 | netfid, | 826 | netfid, li->length, |
822 | li->length, li->offset, | 827 | li->offset, 1, 0, |
823 | 1, 0, li->type, false); | 828 | li->type, false, 0); |
824 | if (stored_rc) | 829 | if (stored_rc) |
825 | rc = stored_rc; | 830 | rc = stored_rc; |
826 | else { | 831 | else { |
@@ -839,31 +844,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
839 | return rc; | 844 | return rc; |
840 | } | 845 | } |
841 | 846 | ||
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 */ | 847 | /* update the file size (if needed) after a write */ |
866 | static void | 848 | void |
867 | cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, | 849 | cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, |
868 | unsigned int bytes_written) | 850 | unsigned int bytes_written) |
869 | { | 851 | { |
@@ -882,7 +864,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
882 | unsigned int total_written; | 864 | unsigned int total_written; |
883 | struct cifs_sb_info *cifs_sb; | 865 | struct cifs_sb_info *cifs_sb; |
884 | struct cifsTconInfo *pTcon; | 866 | struct cifsTconInfo *pTcon; |
885 | int xid, long_op; | 867 | int xid; |
886 | struct cifsFileInfo *open_file; | 868 | struct cifsFileInfo *open_file; |
887 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | 869 | struct cifsInodeInfo *cifsi = CIFS_I(inode); |
888 | 870 | ||
@@ -903,7 +885,6 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
903 | 885 | ||
904 | xid = GetXid(); | 886 | xid = GetXid(); |
905 | 887 | ||
906 | long_op = cifs_write_timeout(cifsi, *poffset); | ||
907 | for (total_written = 0; write_size > total_written; | 888 | for (total_written = 0; write_size > total_written; |
908 | total_written += bytes_written) { | 889 | total_written += bytes_written) { |
909 | rc = -EAGAIN; | 890 | rc = -EAGAIN; |
@@ -931,7 +912,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
931 | min_t(const int, cifs_sb->wsize, | 912 | min_t(const int, cifs_sb->wsize, |
932 | write_size - total_written), | 913 | write_size - total_written), |
933 | *poffset, &bytes_written, | 914 | *poffset, &bytes_written, |
934 | NULL, write_data + total_written, long_op); | 915 | NULL, write_data + total_written, 0); |
935 | } | 916 | } |
936 | if (rc || (bytes_written == 0)) { | 917 | if (rc || (bytes_written == 0)) { |
937 | if (total_written) | 918 | if (total_written) |
@@ -944,8 +925,6 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
944 | cifs_update_eof(cifsi, *poffset, bytes_written); | 925 | cifs_update_eof(cifsi, *poffset, bytes_written); |
945 | *poffset += bytes_written; | 926 | *poffset += bytes_written; |
946 | } | 927 | } |
947 | long_op = CIFS_STD_OP; /* subsequent writes fast - | ||
948 | 15 seconds is plenty */ | ||
949 | } | 928 | } |
950 | 929 | ||
951 | cifs_stats_bytes_written(pTcon, total_written); | 930 | cifs_stats_bytes_written(pTcon, total_written); |
@@ -974,7 +953,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
974 | unsigned int total_written; | 953 | unsigned int total_written; |
975 | struct cifs_sb_info *cifs_sb; | 954 | struct cifs_sb_info *cifs_sb; |
976 | struct cifsTconInfo *pTcon; | 955 | struct cifsTconInfo *pTcon; |
977 | int xid, long_op; | 956 | int xid; |
978 | struct dentry *dentry = open_file->dentry; | 957 | struct dentry *dentry = open_file->dentry; |
979 | struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode); | 958 | struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode); |
980 | 959 | ||
@@ -987,7 +966,6 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
987 | 966 | ||
988 | xid = GetXid(); | 967 | xid = GetXid(); |
989 | 968 | ||
990 | long_op = cifs_write_timeout(cifsi, *poffset); | ||
991 | for (total_written = 0; write_size > total_written; | 969 | for (total_written = 0; write_size > total_written; |
992 | total_written += bytes_written) { | 970 | total_written += bytes_written) { |
993 | rc = -EAGAIN; | 971 | rc = -EAGAIN; |
@@ -1017,7 +995,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
1017 | rc = CIFSSMBWrite2(xid, pTcon, | 995 | rc = CIFSSMBWrite2(xid, pTcon, |
1018 | open_file->netfid, len, | 996 | open_file->netfid, len, |
1019 | *poffset, &bytes_written, | 997 | *poffset, &bytes_written, |
1020 | iov, 1, long_op); | 998 | iov, 1, 0); |
1021 | } else | 999 | } else |
1022 | rc = CIFSSMBWrite(xid, pTcon, | 1000 | rc = CIFSSMBWrite(xid, pTcon, |
1023 | open_file->netfid, | 1001 | open_file->netfid, |
@@ -1025,7 +1003,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
1025 | write_size - total_written), | 1003 | write_size - total_written), |
1026 | *poffset, &bytes_written, | 1004 | *poffset, &bytes_written, |
1027 | write_data + total_written, | 1005 | write_data + total_written, |
1028 | NULL, long_op); | 1006 | NULL, 0); |
1029 | } | 1007 | } |
1030 | if (rc || (bytes_written == 0)) { | 1008 | if (rc || (bytes_written == 0)) { |
1031 | if (total_written) | 1009 | if (total_written) |
@@ -1038,8 +1016,6 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
1038 | cifs_update_eof(cifsi, *poffset, bytes_written); | 1016 | cifs_update_eof(cifsi, *poffset, bytes_written); |
1039 | *poffset += bytes_written; | 1017 | *poffset += bytes_written; |
1040 | } | 1018 | } |
1041 | long_op = CIFS_STD_OP; /* subsequent writes fast - | ||
1042 | 15 seconds is plenty */ | ||
1043 | } | 1019 | } |
1044 | 1020 | ||
1045 | cifs_stats_bytes_written(pTcon, total_written); | 1021 | cifs_stats_bytes_written(pTcon, total_written); |
@@ -1167,7 +1143,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | |||
1167 | char *write_data; | 1143 | char *write_data; |
1168 | int rc = -EFAULT; | 1144 | int rc = -EFAULT; |
1169 | int bytes_written = 0; | 1145 | int bytes_written = 0; |
1170 | struct cifs_sb_info *cifs_sb; | ||
1171 | struct inode *inode; | 1146 | struct inode *inode; |
1172 | struct cifsFileInfo *open_file; | 1147 | struct cifsFileInfo *open_file; |
1173 | 1148 | ||
@@ -1175,7 +1150,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | |||
1175 | return -EFAULT; | 1150 | return -EFAULT; |
1176 | 1151 | ||
1177 | inode = page->mapping->host; | 1152 | inode = page->mapping->host; |
1178 | cifs_sb = CIFS_SB(inode->i_sb); | ||
1179 | 1153 | ||
1180 | offset += (loff_t)from; | 1154 | offset += (loff_t)from; |
1181 | write_data = kmap(page); | 1155 | write_data = kmap(page); |
@@ -1239,7 +1213,7 @@ static int cifs_writepages(struct address_space *mapping, | |||
1239 | struct pagevec pvec; | 1213 | struct pagevec pvec; |
1240 | int rc = 0; | 1214 | int rc = 0; |
1241 | int scanned = 0; | 1215 | int scanned = 0; |
1242 | int xid, long_op; | 1216 | int xid; |
1243 | 1217 | ||
1244 | cifs_sb = CIFS_SB(mapping->host->i_sb); | 1218 | cifs_sb = CIFS_SB(mapping->host->i_sb); |
1245 | 1219 | ||
@@ -1377,43 +1351,67 @@ retry: | |||
1377 | break; | 1351 | break; |
1378 | } | 1352 | } |
1379 | if (n_iov) { | 1353 | if (n_iov) { |
1354 | retry_write: | ||
1380 | open_file = find_writable_file(CIFS_I(mapping->host), | 1355 | open_file = find_writable_file(CIFS_I(mapping->host), |
1381 | false); | 1356 | false); |
1382 | if (!open_file) { | 1357 | if (!open_file) { |
1383 | cERROR(1, "No writable handles for inode"); | 1358 | cERROR(1, "No writable handles for inode"); |
1384 | rc = -EBADF; | 1359 | rc = -EBADF; |
1385 | } else { | 1360 | } else { |
1386 | long_op = cifs_write_timeout(cifsi, offset); | ||
1387 | rc = CIFSSMBWrite2(xid, tcon, open_file->netfid, | 1361 | rc = CIFSSMBWrite2(xid, tcon, open_file->netfid, |
1388 | bytes_to_write, offset, | 1362 | bytes_to_write, offset, |
1389 | &bytes_written, iov, n_iov, | 1363 | &bytes_written, iov, n_iov, |
1390 | long_op); | 1364 | 0); |
1391 | cifsFileInfo_put(open_file); | 1365 | cifsFileInfo_put(open_file); |
1392 | cifs_update_eof(cifsi, offset, bytes_written); | ||
1393 | } | 1366 | } |
1394 | 1367 | ||
1395 | if (rc || bytes_written < bytes_to_write) { | 1368 | cFYI(1, "Write2 rc=%d, wrote=%u", rc, bytes_written); |
1396 | cERROR(1, "Write2 ret %d, wrote %d", | 1369 | |
1397 | rc, bytes_written); | 1370 | /* |
1398 | mapping_set_error(mapping, rc); | 1371 | * For now, treat a short write as if nothing got |
1399 | } else { | 1372 | * written. A zero length write however indicates |
1373 | * ENOSPC or EFBIG. We have no way to know which | ||
1374 | * though, so call it ENOSPC for now. EFBIG would | ||
1375 | * get translated to AS_EIO anyway. | ||
1376 | * | ||
1377 | * FIXME: make it take into account the data that did | ||
1378 | * get written | ||
1379 | */ | ||
1380 | if (rc == 0) { | ||
1381 | if (bytes_written == 0) | ||
1382 | rc = -ENOSPC; | ||
1383 | else if (bytes_written < bytes_to_write) | ||
1384 | rc = -EAGAIN; | ||
1385 | } | ||
1386 | |||
1387 | /* retry on data-integrity flush */ | ||
1388 | if (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN) | ||
1389 | goto retry_write; | ||
1390 | |||
1391 | /* fix the stats and EOF */ | ||
1392 | if (bytes_written > 0) { | ||
1400 | cifs_stats_bytes_written(tcon, bytes_written); | 1393 | cifs_stats_bytes_written(tcon, bytes_written); |
1394 | cifs_update_eof(cifsi, offset, bytes_written); | ||
1401 | } | 1395 | } |
1402 | 1396 | ||
1403 | for (i = 0; i < n_iov; i++) { | 1397 | for (i = 0; i < n_iov; i++) { |
1404 | page = pvec.pages[first + i]; | 1398 | page = pvec.pages[first + i]; |
1405 | /* Should we also set page error on | 1399 | /* on retryable write error, redirty page */ |
1406 | success rc but too little data written? */ | 1400 | if (rc == -EAGAIN) |
1407 | /* BB investigate retry logic on temporary | 1401 | redirty_page_for_writepage(wbc, page); |
1408 | server crash cases and how recovery works | 1402 | else if (rc != 0) |
1409 | when page marked as error */ | ||
1410 | if (rc) | ||
1411 | SetPageError(page); | 1403 | SetPageError(page); |
1412 | kunmap(page); | 1404 | kunmap(page); |
1413 | unlock_page(page); | 1405 | unlock_page(page); |
1414 | end_page_writeback(page); | 1406 | end_page_writeback(page); |
1415 | page_cache_release(page); | 1407 | page_cache_release(page); |
1416 | } | 1408 | } |
1409 | |||
1410 | if (rc != -EAGAIN) | ||
1411 | mapping_set_error(mapping, rc); | ||
1412 | else | ||
1413 | rc = 0; | ||
1414 | |||
1417 | if ((wbc->nr_to_write -= n_iov) <= 0) | 1415 | if ((wbc->nr_to_write -= n_iov) <= 0) |
1418 | done = 1; | 1416 | done = 1; |
1419 | index = next; | 1417 | index = next; |
@@ -1525,27 +1523,47 @@ static int cifs_write_end(struct file *file, struct address_space *mapping, | |||
1525 | return rc; | 1523 | return rc; |
1526 | } | 1524 | } |
1527 | 1525 | ||
1528 | int cifs_fsync(struct file *file, int datasync) | 1526 | int cifs_strict_fsync(struct file *file, int datasync) |
1529 | { | 1527 | { |
1530 | int xid; | 1528 | int xid; |
1531 | int rc = 0; | 1529 | int rc = 0; |
1532 | struct cifsTconInfo *tcon; | 1530 | struct cifsTconInfo *tcon; |
1533 | struct cifsFileInfo *smbfile = file->private_data; | 1531 | struct cifsFileInfo *smbfile = file->private_data; |
1534 | struct inode *inode = file->f_path.dentry->d_inode; | 1532 | struct inode *inode = file->f_path.dentry->d_inode; |
1533 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
1535 | 1534 | ||
1536 | xid = GetXid(); | 1535 | xid = GetXid(); |
1537 | 1536 | ||
1538 | cFYI(1, "Sync file - name: %s datasync: 0x%x", | 1537 | cFYI(1, "Sync file - name: %s datasync: 0x%x", |
1539 | file->f_path.dentry->d_name.name, datasync); | 1538 | file->f_path.dentry->d_name.name, datasync); |
1540 | 1539 | ||
1541 | rc = filemap_write_and_wait(inode->i_mapping); | 1540 | if (!CIFS_I(inode)->clientCanCacheRead) |
1542 | if (rc == 0) { | 1541 | cifs_invalidate_mapping(inode); |
1543 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
1544 | 1542 | ||
1545 | tcon = tlink_tcon(smbfile->tlink); | 1543 | tcon = tlink_tcon(smbfile->tlink); |
1546 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | 1544 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) |
1547 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | 1545 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); |
1548 | } | 1546 | |
1547 | FreeXid(xid); | ||
1548 | return rc; | ||
1549 | } | ||
1550 | |||
1551 | int cifs_fsync(struct file *file, int datasync) | ||
1552 | { | ||
1553 | int xid; | ||
1554 | int rc = 0; | ||
1555 | struct cifsTconInfo *tcon; | ||
1556 | struct cifsFileInfo *smbfile = file->private_data; | ||
1557 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | ||
1558 | |||
1559 | xid = GetXid(); | ||
1560 | |||
1561 | cFYI(1, "Sync file - name: %s datasync: 0x%x", | ||
1562 | file->f_path.dentry->d_name.name, datasync); | ||
1563 | |||
1564 | tcon = tlink_tcon(smbfile->tlink); | ||
1565 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | ||
1566 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | ||
1549 | 1567 | ||
1550 | FreeXid(xid); | 1568 | FreeXid(xid); |
1551 | return rc; | 1569 | return rc; |
@@ -1596,42 +1614,244 @@ int cifs_flush(struct file *file, fl_owner_t id) | |||
1596 | return rc; | 1614 | return rc; |
1597 | } | 1615 | } |
1598 | 1616 | ||
1599 | ssize_t cifs_user_read(struct file *file, char __user *read_data, | 1617 | static int |
1600 | size_t read_size, loff_t *poffset) | 1618 | cifs_write_allocate_pages(struct page **pages, unsigned long num_pages) |
1601 | { | 1619 | { |
1602 | int rc = -EACCES; | 1620 | int rc = 0; |
1621 | unsigned long i; | ||
1622 | |||
1623 | for (i = 0; i < num_pages; i++) { | ||
1624 | pages[i] = alloc_page(__GFP_HIGHMEM); | ||
1625 | if (!pages[i]) { | ||
1626 | /* | ||
1627 | * save number of pages we have already allocated and | ||
1628 | * return with ENOMEM error | ||
1629 | */ | ||
1630 | num_pages = i; | ||
1631 | rc = -ENOMEM; | ||
1632 | goto error; | ||
1633 | } | ||
1634 | } | ||
1635 | |||
1636 | return rc; | ||
1637 | |||
1638 | error: | ||
1639 | for (i = 0; i < num_pages; i++) | ||
1640 | put_page(pages[i]); | ||
1641 | return rc; | ||
1642 | } | ||
1643 | |||
1644 | static inline | ||
1645 | size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len) | ||
1646 | { | ||
1647 | size_t num_pages; | ||
1648 | size_t clen; | ||
1649 | |||
1650 | clen = min_t(const size_t, len, wsize); | ||
1651 | num_pages = clen / PAGE_CACHE_SIZE; | ||
1652 | if (clen % PAGE_CACHE_SIZE) | ||
1653 | num_pages++; | ||
1654 | |||
1655 | if (cur_len) | ||
1656 | *cur_len = clen; | ||
1657 | |||
1658 | return num_pages; | ||
1659 | } | ||
1660 | |||
1661 | static ssize_t | ||
1662 | cifs_iovec_write(struct file *file, const struct iovec *iov, | ||
1663 | unsigned long nr_segs, loff_t *poffset) | ||
1664 | { | ||
1665 | unsigned int written; | ||
1666 | unsigned long num_pages, npages, i; | ||
1667 | size_t copied, len, cur_len; | ||
1668 | ssize_t total_written = 0; | ||
1669 | struct kvec *to_send; | ||
1670 | struct page **pages; | ||
1671 | struct iov_iter it; | ||
1672 | struct inode *inode; | ||
1673 | struct cifsFileInfo *open_file; | ||
1674 | struct cifsTconInfo *pTcon; | ||
1675 | struct cifs_sb_info *cifs_sb; | ||
1676 | int xid, rc; | ||
1677 | |||
1678 | len = iov_length(iov, nr_segs); | ||
1679 | if (!len) | ||
1680 | return 0; | ||
1681 | |||
1682 | rc = generic_write_checks(file, poffset, &len, 0); | ||
1683 | if (rc) | ||
1684 | return rc; | ||
1685 | |||
1686 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | ||
1687 | num_pages = get_numpages(cifs_sb->wsize, len, &cur_len); | ||
1688 | |||
1689 | pages = kmalloc(sizeof(struct pages *)*num_pages, GFP_KERNEL); | ||
1690 | if (!pages) | ||
1691 | return -ENOMEM; | ||
1692 | |||
1693 | to_send = kmalloc(sizeof(struct kvec)*(num_pages + 1), GFP_KERNEL); | ||
1694 | if (!to_send) { | ||
1695 | kfree(pages); | ||
1696 | return -ENOMEM; | ||
1697 | } | ||
1698 | |||
1699 | rc = cifs_write_allocate_pages(pages, num_pages); | ||
1700 | if (rc) { | ||
1701 | kfree(pages); | ||
1702 | kfree(to_send); | ||
1703 | return rc; | ||
1704 | } | ||
1705 | |||
1706 | xid = GetXid(); | ||
1707 | open_file = file->private_data; | ||
1708 | pTcon = tlink_tcon(open_file->tlink); | ||
1709 | inode = file->f_path.dentry->d_inode; | ||
1710 | |||
1711 | iov_iter_init(&it, iov, nr_segs, len, 0); | ||
1712 | npages = num_pages; | ||
1713 | |||
1714 | do { | ||
1715 | size_t save_len = cur_len; | ||
1716 | for (i = 0; i < npages; i++) { | ||
1717 | copied = min_t(const size_t, cur_len, PAGE_CACHE_SIZE); | ||
1718 | copied = iov_iter_copy_from_user(pages[i], &it, 0, | ||
1719 | copied); | ||
1720 | cur_len -= copied; | ||
1721 | iov_iter_advance(&it, copied); | ||
1722 | to_send[i+1].iov_base = kmap(pages[i]); | ||
1723 | to_send[i+1].iov_len = copied; | ||
1724 | } | ||
1725 | |||
1726 | cur_len = save_len - cur_len; | ||
1727 | |||
1728 | do { | ||
1729 | if (open_file->invalidHandle) { | ||
1730 | rc = cifs_reopen_file(open_file, false); | ||
1731 | if (rc != 0) | ||
1732 | break; | ||
1733 | } | ||
1734 | rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, | ||
1735 | cur_len, *poffset, &written, | ||
1736 | to_send, npages, 0); | ||
1737 | } while (rc == -EAGAIN); | ||
1738 | |||
1739 | for (i = 0; i < npages; i++) | ||
1740 | kunmap(pages[i]); | ||
1741 | |||
1742 | if (written) { | ||
1743 | len -= written; | ||
1744 | total_written += written; | ||
1745 | cifs_update_eof(CIFS_I(inode), *poffset, written); | ||
1746 | *poffset += written; | ||
1747 | } else if (rc < 0) { | ||
1748 | if (!total_written) | ||
1749 | total_written = rc; | ||
1750 | break; | ||
1751 | } | ||
1752 | |||
1753 | /* get length and number of kvecs of the next write */ | ||
1754 | npages = get_numpages(cifs_sb->wsize, len, &cur_len); | ||
1755 | } while (len > 0); | ||
1756 | |||
1757 | if (total_written > 0) { | ||
1758 | spin_lock(&inode->i_lock); | ||
1759 | if (*poffset > inode->i_size) | ||
1760 | i_size_write(inode, *poffset); | ||
1761 | spin_unlock(&inode->i_lock); | ||
1762 | } | ||
1763 | |||
1764 | cifs_stats_bytes_written(pTcon, total_written); | ||
1765 | mark_inode_dirty_sync(inode); | ||
1766 | |||
1767 | for (i = 0; i < num_pages; i++) | ||
1768 | put_page(pages[i]); | ||
1769 | kfree(to_send); | ||
1770 | kfree(pages); | ||
1771 | FreeXid(xid); | ||
1772 | return total_written; | ||
1773 | } | ||
1774 | |||
1775 | static ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, | ||
1776 | unsigned long nr_segs, loff_t pos) | ||
1777 | { | ||
1778 | ssize_t written; | ||
1779 | struct inode *inode; | ||
1780 | |||
1781 | inode = iocb->ki_filp->f_path.dentry->d_inode; | ||
1782 | |||
1783 | /* | ||
1784 | * BB - optimize the way when signing is disabled. We can drop this | ||
1785 | * extra memory-to-memory copying and use iovec buffers for constructing | ||
1786 | * write request. | ||
1787 | */ | ||
1788 | |||
1789 | written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos); | ||
1790 | if (written > 0) { | ||
1791 | CIFS_I(inode)->invalid_mapping = true; | ||
1792 | iocb->ki_pos = pos; | ||
1793 | } | ||
1794 | |||
1795 | return written; | ||
1796 | } | ||
1797 | |||
1798 | ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, | ||
1799 | unsigned long nr_segs, loff_t pos) | ||
1800 | { | ||
1801 | struct inode *inode; | ||
1802 | |||
1803 | inode = iocb->ki_filp->f_path.dentry->d_inode; | ||
1804 | |||
1805 | if (CIFS_I(inode)->clientCanCacheAll) | ||
1806 | return generic_file_aio_write(iocb, iov, nr_segs, pos); | ||
1807 | |||
1808 | /* | ||
1809 | * In strict cache mode we need to write the data to the server exactly | ||
1810 | * from the pos to pos+len-1 rather than flush all affected pages | ||
1811 | * because it may cause a error with mandatory locks on these pages but | ||
1812 | * not on the region from pos to ppos+len-1. | ||
1813 | */ | ||
1814 | |||
1815 | return cifs_user_writev(iocb, iov, nr_segs, pos); | ||
1816 | } | ||
1817 | |||
1818 | static ssize_t | ||
1819 | cifs_iovec_read(struct file *file, const struct iovec *iov, | ||
1820 | unsigned long nr_segs, loff_t *poffset) | ||
1821 | { | ||
1822 | int rc; | ||
1823 | int xid; | ||
1824 | ssize_t total_read; | ||
1603 | unsigned int bytes_read = 0; | 1825 | unsigned int bytes_read = 0; |
1604 | unsigned int total_read = 0; | 1826 | size_t len, cur_len; |
1605 | unsigned int current_read_size; | 1827 | int iov_offset = 0; |
1606 | struct cifs_sb_info *cifs_sb; | 1828 | struct cifs_sb_info *cifs_sb; |
1607 | struct cifsTconInfo *pTcon; | 1829 | struct cifsTconInfo *pTcon; |
1608 | int xid; | ||
1609 | struct cifsFileInfo *open_file; | 1830 | struct cifsFileInfo *open_file; |
1610 | char *smb_read_data; | ||
1611 | char __user *current_offset; | ||
1612 | struct smb_com_read_rsp *pSMBr; | 1831 | struct smb_com_read_rsp *pSMBr; |
1832 | char *read_data; | ||
1833 | |||
1834 | if (!nr_segs) | ||
1835 | return 0; | ||
1836 | |||
1837 | len = iov_length(iov, nr_segs); | ||
1838 | if (!len) | ||
1839 | return 0; | ||
1613 | 1840 | ||
1614 | xid = GetXid(); | 1841 | xid = GetXid(); |
1615 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 1842 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
1616 | 1843 | ||
1617 | if (file->private_data == NULL) { | ||
1618 | rc = -EBADF; | ||
1619 | FreeXid(xid); | ||
1620 | return rc; | ||
1621 | } | ||
1622 | open_file = file->private_data; | 1844 | open_file = file->private_data; |
1623 | pTcon = tlink_tcon(open_file->tlink); | 1845 | pTcon = tlink_tcon(open_file->tlink); |
1624 | 1846 | ||
1625 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | 1847 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) |
1626 | cFYI(1, "attempting read on write only file instance"); | 1848 | cFYI(1, "attempting read on write only file instance"); |
1627 | 1849 | ||
1628 | for (total_read = 0, current_offset = read_data; | 1850 | for (total_read = 0; total_read < len; total_read += bytes_read) { |
1629 | read_size > total_read; | 1851 | 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; | 1852 | rc = -EAGAIN; |
1634 | smb_read_data = NULL; | 1853 | read_data = NULL; |
1854 | |||
1635 | while (rc == -EAGAIN) { | 1855 | while (rc == -EAGAIN) { |
1636 | int buf_type = CIFS_NO_BUFFER; | 1856 | int buf_type = CIFS_NO_BUFFER; |
1637 | if (open_file->invalidHandle) { | 1857 | if (open_file->invalidHandle) { |
@@ -1639,27 +1859,25 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
1639 | if (rc != 0) | 1859 | if (rc != 0) |
1640 | break; | 1860 | break; |
1641 | } | 1861 | } |
1642 | rc = CIFSSMBRead(xid, pTcon, | 1862 | rc = CIFSSMBRead(xid, pTcon, open_file->netfid, |
1643 | open_file->netfid, | 1863 | cur_len, *poffset, &bytes_read, |
1644 | current_read_size, *poffset, | 1864 | &read_data, &buf_type); |
1645 | &bytes_read, &smb_read_data, | 1865 | pSMBr = (struct smb_com_read_rsp *)read_data; |
1646 | &buf_type); | 1866 | if (read_data) { |
1647 | pSMBr = (struct smb_com_read_rsp *)smb_read_data; | 1867 | char *data_offset = read_data + 4 + |
1648 | if (smb_read_data) { | 1868 | le16_to_cpu(pSMBr->DataOffset); |
1649 | if (copy_to_user(current_offset, | 1869 | if (memcpy_toiovecend(iov, data_offset, |
1650 | smb_read_data + | 1870 | iov_offset, bytes_read)) |
1651 | 4 /* RFC1001 length field */ + | ||
1652 | le16_to_cpu(pSMBr->DataOffset), | ||
1653 | bytes_read)) | ||
1654 | rc = -EFAULT; | 1871 | rc = -EFAULT; |
1655 | |||
1656 | if (buf_type == CIFS_SMALL_BUFFER) | 1872 | if (buf_type == CIFS_SMALL_BUFFER) |
1657 | cifs_small_buf_release(smb_read_data); | 1873 | cifs_small_buf_release(read_data); |
1658 | else if (buf_type == CIFS_LARGE_BUFFER) | 1874 | else if (buf_type == CIFS_LARGE_BUFFER) |
1659 | cifs_buf_release(smb_read_data); | 1875 | cifs_buf_release(read_data); |
1660 | smb_read_data = NULL; | 1876 | read_data = NULL; |
1877 | iov_offset += bytes_read; | ||
1661 | } | 1878 | } |
1662 | } | 1879 | } |
1880 | |||
1663 | if (rc || (bytes_read == 0)) { | 1881 | if (rc || (bytes_read == 0)) { |
1664 | if (total_read) { | 1882 | if (total_read) { |
1665 | break; | 1883 | break; |
@@ -1672,13 +1890,57 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
1672 | *poffset += bytes_read; | 1890 | *poffset += bytes_read; |
1673 | } | 1891 | } |
1674 | } | 1892 | } |
1893 | |||
1675 | FreeXid(xid); | 1894 | FreeXid(xid); |
1676 | return total_read; | 1895 | return total_read; |
1677 | } | 1896 | } |
1678 | 1897 | ||
1898 | ssize_t cifs_user_read(struct file *file, char __user *read_data, | ||
1899 | size_t read_size, loff_t *poffset) | ||
1900 | { | ||
1901 | struct iovec iov; | ||
1902 | iov.iov_base = read_data; | ||
1903 | iov.iov_len = read_size; | ||
1904 | |||
1905 | return cifs_iovec_read(file, &iov, 1, poffset); | ||
1906 | } | ||
1907 | |||
1908 | static ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, | ||
1909 | unsigned long nr_segs, loff_t pos) | ||
1910 | { | ||
1911 | ssize_t read; | ||
1912 | |||
1913 | read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos); | ||
1914 | if (read > 0) | ||
1915 | iocb->ki_pos = pos; | ||
1916 | |||
1917 | return read; | ||
1918 | } | ||
1919 | |||
1920 | ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, | ||
1921 | unsigned long nr_segs, loff_t pos) | ||
1922 | { | ||
1923 | struct inode *inode; | ||
1924 | |||
1925 | inode = iocb->ki_filp->f_path.dentry->d_inode; | ||
1926 | |||
1927 | if (CIFS_I(inode)->clientCanCacheRead) | ||
1928 | return generic_file_aio_read(iocb, iov, nr_segs, pos); | ||
1929 | |||
1930 | /* | ||
1931 | * In strict cache mode we need to read from the server all the time | ||
1932 | * if we don't have level II oplock because the server can delay mtime | ||
1933 | * change - so we can't make a decision about inode invalidating. | ||
1934 | * And we can also fail with pagereading if there are mandatory locks | ||
1935 | * on pages affected by this read but not on the region from pos to | ||
1936 | * pos+len-1. | ||
1937 | */ | ||
1938 | |||
1939 | return cifs_user_readv(iocb, iov, nr_segs, pos); | ||
1940 | } | ||
1679 | 1941 | ||
1680 | static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | 1942 | static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, |
1681 | loff_t *poffset) | 1943 | loff_t *poffset) |
1682 | { | 1944 | { |
1683 | int rc = -EACCES; | 1945 | int rc = -EACCES; |
1684 | unsigned int bytes_read = 0; | 1946 | unsigned int bytes_read = 0; |
@@ -1746,6 +2008,21 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
1746 | return total_read; | 2008 | return total_read; |
1747 | } | 2009 | } |
1748 | 2010 | ||
2011 | int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) | ||
2012 | { | ||
2013 | int rc, xid; | ||
2014 | struct inode *inode = file->f_path.dentry->d_inode; | ||
2015 | |||
2016 | xid = GetXid(); | ||
2017 | |||
2018 | if (!CIFS_I(inode)->clientCanCacheRead) | ||
2019 | cifs_invalidate_mapping(inode); | ||
2020 | |||
2021 | rc = generic_file_mmap(file, vma); | ||
2022 | FreeXid(xid); | ||
2023 | return rc; | ||
2024 | } | ||
2025 | |||
1749 | int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) | 2026 | int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) |
1750 | { | 2027 | { |
1751 | int rc, xid; | 2028 | int rc, xid; |
@@ -2192,7 +2469,8 @@ void cifs_oplock_break(struct work_struct *work) | |||
2192 | */ | 2469 | */ |
2193 | if (!cfile->oplock_break_cancelled) { | 2470 | if (!cfile->oplock_break_cancelled) { |
2194 | rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0, | 2471 | rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0, |
2195 | 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false); | 2472 | 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false, |
2473 | cinode->clientCanCacheRead ? 1 : 0); | ||
2196 | cFYI(1, "Oplock release rc = %d", rc); | 2474 | cFYI(1, "Oplock release rc = %d", rc); |
2197 | } | 2475 | } |
2198 | 2476 | ||