aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsfs.c1
-rw-r--r--fs/cifs/cifsglob.h1
-rw-r--r--fs/cifs/cifssmb.c4
-rw-r--r--fs/cifs/file.c64
-rw-r--r--fs/cifs/inode.c8
-rw-r--r--fs/cifs/readdir.c2
6 files changed, 61 insertions, 19 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 38491fd3871d..34f5701d9555 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -316,6 +316,7 @@ cifs_alloc_inode(struct super_block *sb)
316 cifs_inode->clientCanCacheAll = false; 316 cifs_inode->clientCanCacheAll = false;
317 cifs_inode->delete_pending = false; 317 cifs_inode->delete_pending = false;
318 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ 318 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
319 cifs_inode->server_eof = 0;
319 320
320 /* Can not set i_flags here - they get immediately overwritten 321 /* Can not set i_flags here - they get immediately overwritten
321 to zero by the VFS */ 322 to zero by the VFS */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 9fbf4dff5da6..7ae19868fdc4 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -370,6 +370,7 @@ struct cifsInodeInfo {
370 bool clientCanCacheAll:1; /* read and writebehind oplock */ 370 bool clientCanCacheAll:1; /* read and writebehind oplock */
371 bool oplockPending:1; 371 bool oplockPending:1;
372 bool delete_pending:1; /* DELETE_ON_CLOSE is set */ 372 bool delete_pending:1; /* DELETE_ON_CLOSE is set */
373 u64 server_eof; /* current file size on server */
373 struct inode vfs_inode; 374 struct inode vfs_inode;
374}; 375};
375 376
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 3f36b1ea03c9..a0845dc7b8a9 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1626,6 +1626,8 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1626 int smb_hdr_len; 1626 int smb_hdr_len;
1627 int resp_buf_type = 0; 1627 int resp_buf_type = 0;
1628 1628
1629 *nbytes = 0;
1630
1629 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count)); 1631 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1630 1632
1631 if (tcon->ses->capabilities & CAP_LARGE_FILES) { 1633 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
@@ -1682,11 +1684,9 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1682 cifs_stats_inc(&tcon->num_writes); 1684 cifs_stats_inc(&tcon->num_writes);
1683 if (rc) { 1685 if (rc) {
1684 cFYI(1, ("Send error Write2 = %d", rc)); 1686 cFYI(1, ("Send error Write2 = %d", rc));
1685 *nbytes = 0;
1686 } else if (resp_buf_type == 0) { 1687 } else if (resp_buf_type == 0) {
1687 /* presumably this can not happen, but best to be safe */ 1688 /* presumably this can not happen, but best to be safe */
1688 rc = -EIO; 1689 rc = -EIO;
1689 *nbytes = 0;
1690 } else { 1690 } else {
1691 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base; 1691 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1692 *nbytes = le16_to_cpu(pSMBr->CountHigh); 1692 *nbytes = le16_to_cpu(pSMBr->CountHigh);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 81747acca4c4..dfd3e6c52a1e 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -971,6 +971,40 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
971 return rc; 971 return rc;
972} 972}
973 973
974/*
975 * Set the timeout on write requests past EOF. For some servers (Windows)
976 * these calls can be very long.
977 *
978 * If we're writing >10M past the EOF we give a 180s timeout. Anything less
979 * than that gets a 45s timeout. Writes not past EOF get 15s timeouts.
980 * The 10M cutoff is totally arbitrary. A better scheme for this would be
981 * welcome if someone wants to suggest one.
982 *
983 * We may be able to do a better job with this if there were some way to
984 * declare that a file should be sparse.
985 */
986static int
987cifs_write_timeout(struct cifsInodeInfo *cifsi, loff_t offset)
988{
989 if (offset <= cifsi->server_eof)
990 return CIFS_STD_OP;
991 else if (offset > (cifsi->server_eof + (10 * 1024 * 1024)))
992 return CIFS_VLONG_OP;
993 else
994 return CIFS_LONG_OP;
995}
996
997/* update the file size (if needed) after a write */
998static void
999cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
1000 unsigned int bytes_written)
1001{
1002 loff_t end_of_write = offset + bytes_written;
1003
1004 if (end_of_write > cifsi->server_eof)
1005 cifsi->server_eof = end_of_write;
1006}
1007
974ssize_t cifs_user_write(struct file *file, const char __user *write_data, 1008ssize_t cifs_user_write(struct file *file, const char __user *write_data,
975 size_t write_size, loff_t *poffset) 1009 size_t write_size, loff_t *poffset)
976{ 1010{
@@ -981,6 +1015,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
981 struct cifsTconInfo *pTcon; 1015 struct cifsTconInfo *pTcon;
982 int xid, long_op; 1016 int xid, long_op;
983 struct cifsFileInfo *open_file; 1017 struct cifsFileInfo *open_file;
1018 struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode);
984 1019
985 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 1020 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
986 1021
@@ -1000,11 +1035,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
1000 1035
1001 xid = GetXid(); 1036 xid = GetXid();
1002 1037
1003 if (*poffset > file->f_path.dentry->d_inode->i_size) 1038 long_op = cifs_write_timeout(cifsi, *poffset);
1004 long_op = CIFS_VLONG_OP; /* writes past EOF take long time */
1005 else
1006 long_op = CIFS_LONG_OP;
1007
1008 for (total_written = 0; write_size > total_written; 1039 for (total_written = 0; write_size > total_written;
1009 total_written += bytes_written) { 1040 total_written += bytes_written) {
1010 rc = -EAGAIN; 1041 rc = -EAGAIN;
@@ -1048,8 +1079,10 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
1048 FreeXid(xid); 1079 FreeXid(xid);
1049 return rc; 1080 return rc;
1050 } 1081 }
1051 } else 1082 } else {
1083 cifs_update_eof(cifsi, *poffset, bytes_written);
1052 *poffset += bytes_written; 1084 *poffset += bytes_written;
1085 }
1053 long_op = CIFS_STD_OP; /* subsequent writes fast - 1086 long_op = CIFS_STD_OP; /* subsequent writes fast -
1054 15 seconds is plenty */ 1087 15 seconds is plenty */
1055 } 1088 }
@@ -1085,6 +1118,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
1085 struct cifsTconInfo *pTcon; 1118 struct cifsTconInfo *pTcon;
1086 int xid, long_op; 1119 int xid, long_op;
1087 struct cifsFileInfo *open_file; 1120 struct cifsFileInfo *open_file;
1121 struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode);
1088 1122
1089 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 1123 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
1090 1124
@@ -1099,11 +1133,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
1099 1133
1100 xid = GetXid(); 1134 xid = GetXid();
1101 1135
1102 if (*poffset > file->f_path.dentry->d_inode->i_size) 1136 long_op = cifs_write_timeout(cifsi, *poffset);
1103 long_op = CIFS_VLONG_OP; /* writes past EOF can be slow */
1104 else
1105 long_op = CIFS_LONG_OP;
1106
1107 for (total_written = 0; write_size > total_written; 1137 for (total_written = 0; write_size > total_written;
1108 total_written += bytes_written) { 1138 total_written += bytes_written) {
1109 rc = -EAGAIN; 1139 rc = -EAGAIN;
@@ -1166,8 +1196,10 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
1166 FreeXid(xid); 1196 FreeXid(xid);
1167 return rc; 1197 return rc;
1168 } 1198 }
1169 } else 1199 } else {
1200 cifs_update_eof(cifsi, *poffset, bytes_written);
1170 *poffset += bytes_written; 1201 *poffset += bytes_written;
1202 }
1171 long_op = CIFS_STD_OP; /* subsequent writes fast - 1203 long_op = CIFS_STD_OP; /* subsequent writes fast -
1172 15 seconds is plenty */ 1204 15 seconds is plenty */
1173 } 1205 }
@@ -1380,11 +1412,12 @@ static int cifs_writepages(struct address_space *mapping,
1380 int nr_pages; 1412 int nr_pages;
1381 __u64 offset = 0; 1413 __u64 offset = 0;
1382 struct cifsFileInfo *open_file; 1414 struct cifsFileInfo *open_file;
1415 struct cifsInodeInfo *cifsi = CIFS_I(mapping->host);
1383 struct page *page; 1416 struct page *page;
1384 struct pagevec pvec; 1417 struct pagevec pvec;
1385 int rc = 0; 1418 int rc = 0;
1386 int scanned = 0; 1419 int scanned = 0;
1387 int xid; 1420 int xid, long_op;
1388 1421
1389 cifs_sb = CIFS_SB(mapping->host->i_sb); 1422 cifs_sb = CIFS_SB(mapping->host->i_sb);
1390 1423
@@ -1528,12 +1561,15 @@ retry:
1528 cERROR(1, ("No writable handles for inode")); 1561 cERROR(1, ("No writable handles for inode"));
1529 rc = -EBADF; 1562 rc = -EBADF;
1530 } else { 1563 } else {
1564 long_op = cifs_write_timeout(cifsi, offset);
1531 rc = CIFSSMBWrite2(xid, cifs_sb->tcon, 1565 rc = CIFSSMBWrite2(xid, cifs_sb->tcon,
1532 open_file->netfid, 1566 open_file->netfid,
1533 bytes_to_write, offset, 1567 bytes_to_write, offset,
1534 &bytes_written, iov, n_iov, 1568 &bytes_written, iov, n_iov,
1535 CIFS_LONG_OP); 1569 long_op);
1536 atomic_dec(&open_file->wrtPending); 1570 atomic_dec(&open_file->wrtPending);
1571 cifs_update_eof(cifsi, offset, bytes_written);
1572
1537 if (rc || bytes_written < bytes_to_write) { 1573 if (rc || bytes_written < bytes_to_write) {
1538 cERROR(1, ("Write2 ret %d, wrote %d", 1574 cERROR(1, ("Write2 ret %d, wrote %d",
1539 rc, bytes_written)); 1575 rc, bytes_written));
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index fceebee39f27..09082ac85185 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -143,6 +143,7 @@ static void cifs_unix_info_to_inode(struct inode *inode,
143 143
144 inode->i_nlink = le64_to_cpu(info->Nlinks); 144 inode->i_nlink = le64_to_cpu(info->Nlinks);
145 145
146 cifsInfo->server_eof = end_of_file;
146 spin_lock(&inode->i_lock); 147 spin_lock(&inode->i_lock);
147 if (is_size_safe_to_change(cifsInfo, end_of_file)) { 148 if (is_size_safe_to_change(cifsInfo, end_of_file)) {
148 /* 149 /*
@@ -606,12 +607,12 @@ int cifs_get_inode_info(struct inode **pinode,
606 inode->i_mode |= S_IFREG; 607 inode->i_mode |= S_IFREG;
607 } 608 }
608 609
610 cifsInfo->server_eof = le64_to_cpu(pfindData->EndOfFile);
609 spin_lock(&inode->i_lock); 611 spin_lock(&inode->i_lock);
610 if (is_size_safe_to_change(cifsInfo, 612 if (is_size_safe_to_change(cifsInfo, cifsInfo->server_eof)) {
611 le64_to_cpu(pfindData->EndOfFile))) {
612 /* can not safely shrink the file size here if the 613 /* can not safely shrink the file size here if the
613 client is writing to it due to potential races */ 614 client is writing to it due to potential races */
614 i_size_write(inode, le64_to_cpu(pfindData->EndOfFile)); 615 i_size_write(inode, cifsInfo->server_eof);
615 616
616 /* 512 bytes (2**9) is the fake blocksize that must be 617 /* 512 bytes (2**9) is the fake blocksize that must be
617 used for this calculation */ 618 used for this calculation */
@@ -1755,6 +1756,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
1755 } 1756 }
1756 1757
1757 if (rc == 0) { 1758 if (rc == 0) {
1759 cifsInode->server_eof = attrs->ia_size;
1758 rc = cifs_vmtruncate(inode, attrs->ia_size); 1760 rc = cifs_vmtruncate(inode, attrs->ia_size);
1759 cifs_truncate_page(inode->i_mapping, inode->i_size); 1761 cifs_truncate_page(inode->i_mapping, inode->i_size);
1760 } 1762 }
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index c3c3e6286af5..1a8be6228333 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -239,6 +239,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
239 if (atomic_read(&cifsInfo->inUse) == 0) 239 if (atomic_read(&cifsInfo->inUse) == 0)
240 atomic_set(&cifsInfo->inUse, 1); 240 atomic_set(&cifsInfo->inUse, 1);
241 241
242 cifsInfo->server_eof = end_of_file;
242 spin_lock(&tmp_inode->i_lock); 243 spin_lock(&tmp_inode->i_lock);
243 if (is_size_safe_to_change(cifsInfo, end_of_file)) { 244 if (is_size_safe_to_change(cifsInfo, end_of_file)) {
244 /* can not safely change the file size here if the 245 /* can not safely change the file size here if the
@@ -375,6 +376,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
375 tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); 376 tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
376 tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); 377 tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
377 378
379 cifsInfo->server_eof = end_of_file;
378 spin_lock(&tmp_inode->i_lock); 380 spin_lock(&tmp_inode->i_lock);
379 if (is_size_safe_to_change(cifsInfo, end_of_file)) { 381 if (is_size_safe_to_change(cifsInfo, end_of_file)) {
380 /* can not safely change the file size here if the 382 /* can not safely change the file size here if the