aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c141
1 files changed, 80 insertions, 61 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 81747acca4c..38c06f82657 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -46,7 +46,7 @@ static inline struct cifsFileInfo *cifs_init_private(
46 memset(private_data, 0, sizeof(struct cifsFileInfo)); 46 memset(private_data, 0, sizeof(struct cifsFileInfo));
47 private_data->netfid = netfid; 47 private_data->netfid = netfid;
48 private_data->pid = current->tgid; 48 private_data->pid = current->tgid;
49 init_MUTEX(&private_data->fh_sem); 49 mutex_init(&private_data->fh_mutex);
50 mutex_init(&private_data->lock_mutex); 50 mutex_init(&private_data->lock_mutex);
51 INIT_LIST_HEAD(&private_data->llist); 51 INIT_LIST_HEAD(&private_data->llist);
52 private_data->pfile = file; /* needed for writepage */ 52 private_data->pfile = file; /* needed for writepage */
@@ -129,15 +129,12 @@ static inline int cifs_posix_open_inode_helper(struct inode *inode,
129 struct file *file, struct cifsInodeInfo *pCifsInode, 129 struct file *file, struct cifsInodeInfo *pCifsInode,
130 struct cifsFileInfo *pCifsFile, int oplock, u16 netfid) 130 struct cifsFileInfo *pCifsFile, int oplock, u16 netfid)
131{ 131{
132 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
133/* struct timespec temp; */ /* BB REMOVEME BB */
134 132
135 file->private_data = kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 133 file->private_data = kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
136 if (file->private_data == NULL) 134 if (file->private_data == NULL)
137 return -ENOMEM; 135 return -ENOMEM;
138 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid); 136 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
139 write_lock(&GlobalSMBSeslock); 137 write_lock(&GlobalSMBSeslock);
140 list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
141 138
142 pCifsInode = CIFS_I(file->f_path.dentry->d_inode); 139 pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
143 if (pCifsInode == NULL) { 140 if (pCifsInode == NULL) {
@@ -145,17 +142,6 @@ static inline int cifs_posix_open_inode_helper(struct inode *inode,
145 return -EINVAL; 142 return -EINVAL;
146 } 143 }
147 144
148 /* want handles we can use to read with first
149 in the list so we do not have to walk the
150 list to search for one in write_begin */
151 if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
152 list_add_tail(&pCifsFile->flist,
153 &pCifsInode->openFileList);
154 } else {
155 list_add(&pCifsFile->flist,
156 &pCifsInode->openFileList);
157 }
158
159 if (pCifsInode->clientCanCacheRead) { 145 if (pCifsInode->clientCanCacheRead) {
160 /* we have the inode open somewhere else 146 /* we have the inode open somewhere else
161 no need to discard cache data */ 147 no need to discard cache data */
@@ -284,35 +270,32 @@ int cifs_open(struct inode *inode, struct file *file)
284 cifs_sb = CIFS_SB(inode->i_sb); 270 cifs_sb = CIFS_SB(inode->i_sb);
285 tcon = cifs_sb->tcon; 271 tcon = cifs_sb->tcon;
286 272
287 if (file->f_flags & O_CREAT) { 273 /* search inode for this file and fill in file->private_data */
288 /* search inode for this file and fill in file->private_data */ 274 pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
289 pCifsInode = CIFS_I(file->f_path.dentry->d_inode); 275 read_lock(&GlobalSMBSeslock);
290 read_lock(&GlobalSMBSeslock); 276 list_for_each(tmp, &pCifsInode->openFileList) {
291 list_for_each(tmp, &pCifsInode->openFileList) { 277 pCifsFile = list_entry(tmp, struct cifsFileInfo,
292 pCifsFile = list_entry(tmp, struct cifsFileInfo, 278 flist);
293 flist); 279 if ((pCifsFile->pfile == NULL) &&
294 if ((pCifsFile->pfile == NULL) && 280 (pCifsFile->pid == current->tgid)) {
295 (pCifsFile->pid == current->tgid)) { 281 /* mode set in cifs_create */
296 /* mode set in cifs_create */ 282
297 283 /* needed for writepage */
298 /* needed for writepage */ 284 pCifsFile->pfile = file;
299 pCifsFile->pfile = file; 285
300 286 file->private_data = pCifsFile;
301 file->private_data = pCifsFile; 287 break;
302 break;
303 }
304 }
305 read_unlock(&GlobalSMBSeslock);
306 if (file->private_data != NULL) {
307 rc = 0;
308 FreeXid(xid);
309 return rc;
310 } else {
311 if (file->f_flags & O_EXCL)
312 cERROR(1, ("could not find file instance for "
313 "new file %p", file));
314 } 288 }
315 } 289 }
290 read_unlock(&GlobalSMBSeslock);
291
292 if (file->private_data != NULL) {
293 rc = 0;
294 FreeXid(xid);
295 return rc;
296 } else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL))
297 cERROR(1, ("could not find file instance for "
298 "new file %p", file));
316 299
317 full_path = build_path_from_dentry(file->f_path.dentry); 300 full_path = build_path_from_dentry(file->f_path.dentry);
318 if (full_path == NULL) { 301 if (full_path == NULL) {
@@ -500,9 +483,9 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
500 return -EBADF; 483 return -EBADF;
501 484
502 xid = GetXid(); 485 xid = GetXid();
503 down(&pCifsFile->fh_sem); 486 mutex_unlock(&pCifsFile->fh_mutex);
504 if (!pCifsFile->invalidHandle) { 487 if (!pCifsFile->invalidHandle) {
505 up(&pCifsFile->fh_sem); 488 mutex_lock(&pCifsFile->fh_mutex);
506 FreeXid(xid); 489 FreeXid(xid);
507 return 0; 490 return 0;
508 } 491 }
@@ -533,7 +516,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
533 if (full_path == NULL) { 516 if (full_path == NULL) {
534 rc = -ENOMEM; 517 rc = -ENOMEM;
535reopen_error_exit: 518reopen_error_exit:
536 up(&pCifsFile->fh_sem); 519 mutex_lock(&pCifsFile->fh_mutex);
537 FreeXid(xid); 520 FreeXid(xid);
538 return rc; 521 return rc;
539 } 522 }
@@ -575,14 +558,14 @@ reopen_error_exit:
575 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 558 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
576 CIFS_MOUNT_MAP_SPECIAL_CHR); 559 CIFS_MOUNT_MAP_SPECIAL_CHR);
577 if (rc) { 560 if (rc) {
578 up(&pCifsFile->fh_sem); 561 mutex_lock(&pCifsFile->fh_mutex);
579 cFYI(1, ("cifs_open returned 0x%x", rc)); 562 cFYI(1, ("cifs_open returned 0x%x", rc));
580 cFYI(1, ("oplock: %d", oplock)); 563 cFYI(1, ("oplock: %d", oplock));
581 } else { 564 } else {
582reopen_success: 565reopen_success:
583 pCifsFile->netfid = netfid; 566 pCifsFile->netfid = netfid;
584 pCifsFile->invalidHandle = false; 567 pCifsFile->invalidHandle = false;
585 up(&pCifsFile->fh_sem); 568 mutex_lock(&pCifsFile->fh_mutex);
586 pCifsInode = CIFS_I(inode); 569 pCifsInode = CIFS_I(inode);
587 if (pCifsInode) { 570 if (pCifsInode) {
588 if (can_flush) { 571 if (can_flush) {
@@ -971,6 +954,40 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
971 return rc; 954 return rc;
972} 955}
973 956
957/*
958 * Set the timeout on write requests past EOF. For some servers (Windows)
959 * these calls can be very long.
960 *
961 * If we're writing >10M past the EOF we give a 180s timeout. Anything less
962 * than that gets a 45s timeout. Writes not past EOF get 15s timeouts.
963 * The 10M cutoff is totally arbitrary. A better scheme for this would be
964 * welcome if someone wants to suggest one.
965 *
966 * We may be able to do a better job with this if there were some way to
967 * declare that a file should be sparse.
968 */
969static int
970cifs_write_timeout(struct cifsInodeInfo *cifsi, loff_t offset)
971{
972 if (offset <= cifsi->server_eof)
973 return CIFS_STD_OP;
974 else if (offset > (cifsi->server_eof + (10 * 1024 * 1024)))
975 return CIFS_VLONG_OP;
976 else
977 return CIFS_LONG_OP;
978}
979
980/* update the file size (if needed) after a write */
981static void
982cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
983 unsigned int bytes_written)
984{
985 loff_t end_of_write = offset + bytes_written;
986
987 if (end_of_write > cifsi->server_eof)
988 cifsi->server_eof = end_of_write;
989}
990
974ssize_t cifs_user_write(struct file *file, const char __user *write_data, 991ssize_t cifs_user_write(struct file *file, const char __user *write_data,
975 size_t write_size, loff_t *poffset) 992 size_t write_size, loff_t *poffset)
976{ 993{
@@ -981,6 +998,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
981 struct cifsTconInfo *pTcon; 998 struct cifsTconInfo *pTcon;
982 int xid, long_op; 999 int xid, long_op;
983 struct cifsFileInfo *open_file; 1000 struct cifsFileInfo *open_file;
1001 struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode);
984 1002
985 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 1003 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
986 1004
@@ -1000,11 +1018,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
1000 1018
1001 xid = GetXid(); 1019 xid = GetXid();
1002 1020
1003 if (*poffset > file->f_path.dentry->d_inode->i_size) 1021 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; 1022 for (total_written = 0; write_size > total_written;
1009 total_written += bytes_written) { 1023 total_written += bytes_written) {
1010 rc = -EAGAIN; 1024 rc = -EAGAIN;
@@ -1048,8 +1062,10 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
1048 FreeXid(xid); 1062 FreeXid(xid);
1049 return rc; 1063 return rc;
1050 } 1064 }
1051 } else 1065 } else {
1066 cifs_update_eof(cifsi, *poffset, bytes_written);
1052 *poffset += bytes_written; 1067 *poffset += bytes_written;
1068 }
1053 long_op = CIFS_STD_OP; /* subsequent writes fast - 1069 long_op = CIFS_STD_OP; /* subsequent writes fast -
1054 15 seconds is plenty */ 1070 15 seconds is plenty */
1055 } 1071 }
@@ -1085,6 +1101,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
1085 struct cifsTconInfo *pTcon; 1101 struct cifsTconInfo *pTcon;
1086 int xid, long_op; 1102 int xid, long_op;
1087 struct cifsFileInfo *open_file; 1103 struct cifsFileInfo *open_file;
1104 struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode);
1088 1105
1089 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 1106 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
1090 1107
@@ -1099,11 +1116,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
1099 1116
1100 xid = GetXid(); 1117 xid = GetXid();
1101 1118
1102 if (*poffset > file->f_path.dentry->d_inode->i_size) 1119 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; 1120 for (total_written = 0; write_size > total_written;
1108 total_written += bytes_written) { 1121 total_written += bytes_written) {
1109 rc = -EAGAIN; 1122 rc = -EAGAIN;
@@ -1166,8 +1179,10 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
1166 FreeXid(xid); 1179 FreeXid(xid);
1167 return rc; 1180 return rc;
1168 } 1181 }
1169 } else 1182 } else {
1183 cifs_update_eof(cifsi, *poffset, bytes_written);
1170 *poffset += bytes_written; 1184 *poffset += bytes_written;
1185 }
1171 long_op = CIFS_STD_OP; /* subsequent writes fast - 1186 long_op = CIFS_STD_OP; /* subsequent writes fast -
1172 15 seconds is plenty */ 1187 15 seconds is plenty */
1173 } 1188 }
@@ -1380,11 +1395,12 @@ static int cifs_writepages(struct address_space *mapping,
1380 int nr_pages; 1395 int nr_pages;
1381 __u64 offset = 0; 1396 __u64 offset = 0;
1382 struct cifsFileInfo *open_file; 1397 struct cifsFileInfo *open_file;
1398 struct cifsInodeInfo *cifsi = CIFS_I(mapping->host);
1383 struct page *page; 1399 struct page *page;
1384 struct pagevec pvec; 1400 struct pagevec pvec;
1385 int rc = 0; 1401 int rc = 0;
1386 int scanned = 0; 1402 int scanned = 0;
1387 int xid; 1403 int xid, long_op;
1388 1404
1389 cifs_sb = CIFS_SB(mapping->host->i_sb); 1405 cifs_sb = CIFS_SB(mapping->host->i_sb);
1390 1406
@@ -1528,12 +1544,15 @@ retry:
1528 cERROR(1, ("No writable handles for inode")); 1544 cERROR(1, ("No writable handles for inode"));
1529 rc = -EBADF; 1545 rc = -EBADF;
1530 } else { 1546 } else {
1547 long_op = cifs_write_timeout(cifsi, offset);
1531 rc = CIFSSMBWrite2(xid, cifs_sb->tcon, 1548 rc = CIFSSMBWrite2(xid, cifs_sb->tcon,
1532 open_file->netfid, 1549 open_file->netfid,
1533 bytes_to_write, offset, 1550 bytes_to_write, offset,
1534 &bytes_written, iov, n_iov, 1551 &bytes_written, iov, n_iov,
1535 CIFS_LONG_OP); 1552 long_op);
1536 atomic_dec(&open_file->wrtPending); 1553 atomic_dec(&open_file->wrtPending);
1554 cifs_update_eof(cifsi, offset, bytes_written);
1555
1537 if (rc || bytes_written < bytes_to_write) { 1556 if (rc || bytes_written < bytes_to_write) {
1538 cERROR(1, ("Write2 ret %d, wrote %d", 1557 cERROR(1, ("Write2 ret %d, wrote %d",
1539 rc, bytes_written)); 1558 rc, bytes_written));