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.c174
1 files changed, 93 insertions, 81 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index c34b7f8a217b..429337eb7afe 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -30,6 +30,7 @@
30#include <linux/writeback.h> 30#include <linux/writeback.h>
31#include <linux/task_io_accounting_ops.h> 31#include <linux/task_io_accounting_ops.h>
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include <linux/mount.h>
33#include <asm/div64.h> 34#include <asm/div64.h>
34#include "cifsfs.h" 35#include "cifsfs.h"
35#include "cifspdu.h" 36#include "cifspdu.h"
@@ -39,29 +40,6 @@
39#include "cifs_debug.h" 40#include "cifs_debug.h"
40#include "cifs_fs_sb.h" 41#include "cifs_fs_sb.h"
41 42
42static inline struct cifsFileInfo *cifs_init_private(
43 struct cifsFileInfo *private_data, struct inode *inode,
44 struct file *file, __u16 netfid)
45{
46 memset(private_data, 0, sizeof(struct cifsFileInfo));
47 private_data->netfid = netfid;
48 private_data->pid = current->tgid;
49 mutex_init(&private_data->fh_mutex);
50 mutex_init(&private_data->lock_mutex);
51 INIT_LIST_HEAD(&private_data->llist);
52 private_data->pfile = file; /* needed for writepage */
53 private_data->pInode = inode;
54 private_data->invalidHandle = false;
55 private_data->closePend = false;
56 /* we have to track num writers to the inode, since writepages
57 does not tell us which handle the write is for so there can
58 be a close (overlapping with write) of the filehandle that
59 cifs_writepages chose to use */
60 atomic_set(&private_data->wrtPending, 0);
61
62 return private_data;
63}
64
65static inline int cifs_convert_flags(unsigned int flags) 43static inline int cifs_convert_flags(unsigned int flags)
66{ 44{
67 if ((flags & O_ACCMODE) == O_RDONLY) 45 if ((flags & O_ACCMODE) == O_RDONLY)
@@ -125,9 +103,11 @@ static inline int cifs_get_disposition(unsigned int flags)
125} 103}
126 104
127/* all arguments to this function must be checked for validity in caller */ 105/* all arguments to this function must be checked for validity in caller */
128static inline int cifs_posix_open_inode_helper(struct inode *inode, 106static inline int
129 struct file *file, struct cifsInodeInfo *pCifsInode, 107cifs_posix_open_inode_helper(struct inode *inode, struct file *file,
130 struct cifsFileInfo *pCifsFile, int oplock, u16 netfid) 108 struct cifsInodeInfo *pCifsInode,
109 struct cifsFileInfo *pCifsFile, __u32 oplock,
110 u16 netfid)
131{ 111{
132 112
133 write_lock(&GlobalSMBSeslock); 113 write_lock(&GlobalSMBSeslock);
@@ -221,17 +201,6 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
221 struct timespec temp; 201 struct timespec temp;
222 int rc; 202 int rc;
223 203
224 /* want handles we can use to read with first
225 in the list so we do not have to walk the
226 list to search for one in write_begin */
227 if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
228 list_add_tail(&pCifsFile->flist,
229 &pCifsInode->openFileList);
230 } else {
231 list_add(&pCifsFile->flist,
232 &pCifsInode->openFileList);
233 }
234 write_unlock(&GlobalSMBSeslock);
235 if (pCifsInode->clientCanCacheRead) { 204 if (pCifsInode->clientCanCacheRead) {
236 /* we have the inode open somewhere else 205 /* we have the inode open somewhere else
237 no need to discard cache data */ 206 no need to discard cache data */
@@ -281,7 +250,8 @@ client_can_cache:
281int cifs_open(struct inode *inode, struct file *file) 250int cifs_open(struct inode *inode, struct file *file)
282{ 251{
283 int rc = -EACCES; 252 int rc = -EACCES;
284 int xid, oplock; 253 int xid;
254 __u32 oplock;
285 struct cifs_sb_info *cifs_sb; 255 struct cifs_sb_info *cifs_sb;
286 struct cifsTconInfo *tcon; 256 struct cifsTconInfo *tcon;
287 struct cifsFileInfo *pCifsFile; 257 struct cifsFileInfo *pCifsFile;
@@ -326,7 +296,7 @@ int cifs_open(struct inode *inode, struct file *file)
326 le64_to_cpu(tcon->fsUnixInfo.Capability))) { 296 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
327 int oflags = (int) cifs_posix_convert_flags(file->f_flags); 297 int oflags = (int) cifs_posix_convert_flags(file->f_flags);
328 /* can not refresh inode info since size could be stale */ 298 /* can not refresh inode info since size could be stale */
329 rc = cifs_posix_open(full_path, &inode, inode->i_sb, 299 rc = cifs_posix_open(full_path, &inode, file->f_path.mnt,
330 cifs_sb->mnt_file_mode /* ignored */, 300 cifs_sb->mnt_file_mode /* ignored */,
331 oflags, &oplock, &netfid, xid); 301 oflags, &oplock, &netfid, xid);
332 if (rc == 0) { 302 if (rc == 0) {
@@ -416,24 +386,17 @@ int cifs_open(struct inode *inode, struct file *file)
416 cFYI(1, ("cifs_open returned 0x%x", rc)); 386 cFYI(1, ("cifs_open returned 0x%x", rc));
417 goto out; 387 goto out;
418 } 388 }
419 file->private_data = 389
420 kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 390 pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt,
391 file->f_flags);
392 file->private_data = pCifsFile;
421 if (file->private_data == NULL) { 393 if (file->private_data == NULL) {
422 rc = -ENOMEM; 394 rc = -ENOMEM;
423 goto out; 395 goto out;
424 } 396 }
425 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
426 write_lock(&GlobalSMBSeslock);
427 list_add(&pCifsFile->tlist, &tcon->openFileList);
428 397
429 pCifsInode = CIFS_I(file->f_path.dentry->d_inode); 398 rc = cifs_open_inode_helper(inode, file, pCifsInode, pCifsFile, tcon,
430 if (pCifsInode) { 399 &oplock, buf, full_path, xid);
431 rc = cifs_open_inode_helper(inode, file, pCifsInode,
432 pCifsFile, tcon,
433 &oplock, buf, full_path, xid);
434 } else {
435 write_unlock(&GlobalSMBSeslock);
436 }
437 400
438 if (oplock & CIFS_CREATE_ACTION) { 401 if (oplock & CIFS_CREATE_ACTION) {
439 /* time to set mode which we can not set earlier due to 402 /* time to set mode which we can not set earlier due to
@@ -476,7 +439,8 @@ static int cifs_relock_file(struct cifsFileInfo *cifsFile)
476static int cifs_reopen_file(struct file *file, bool can_flush) 439static int cifs_reopen_file(struct file *file, bool can_flush)
477{ 440{
478 int rc = -EACCES; 441 int rc = -EACCES;
479 int xid, oplock; 442 int xid;
443 __u32 oplock;
480 struct cifs_sb_info *cifs_sb; 444 struct cifs_sb_info *cifs_sb;
481 struct cifsTconInfo *tcon; 445 struct cifsTconInfo *tcon;
482 struct cifsFileInfo *pCifsFile; 446 struct cifsFileInfo *pCifsFile;
@@ -545,7 +509,7 @@ reopen_error_exit:
545 le64_to_cpu(tcon->fsUnixInfo.Capability))) { 509 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
546 int oflags = (int) cifs_posix_convert_flags(file->f_flags); 510 int oflags = (int) cifs_posix_convert_flags(file->f_flags);
547 /* can not refresh inode info since size could be stale */ 511 /* can not refresh inode info since size could be stale */
548 rc = cifs_posix_open(full_path, NULL, inode->i_sb, 512 rc = cifs_posix_open(full_path, NULL, file->f_path.mnt,
549 cifs_sb->mnt_file_mode /* ignored */, 513 cifs_sb->mnt_file_mode /* ignored */,
550 oflags, &oplock, &netfid, xid); 514 oflags, &oplock, &netfid, xid);
551 if (rc == 0) { 515 if (rc == 0) {
@@ -643,7 +607,7 @@ int cifs_close(struct inode *inode, struct file *file)
643 if (!pTcon->need_reconnect) { 607 if (!pTcon->need_reconnect) {
644 write_unlock(&GlobalSMBSeslock); 608 write_unlock(&GlobalSMBSeslock);
645 timeout = 2; 609 timeout = 2;
646 while ((atomic_read(&pSMBFile->wrtPending) != 0) 610 while ((atomic_read(&pSMBFile->count) != 1)
647 && (timeout <= 2048)) { 611 && (timeout <= 2048)) {
648 /* Give write a better chance to get to 612 /* Give write a better chance to get to
649 server ahead of the close. We do not 613 server ahead of the close. We do not
@@ -657,8 +621,6 @@ int cifs_close(struct inode *inode, struct file *file)
657 msleep(timeout); 621 msleep(timeout);
658 timeout *= 4; 622 timeout *= 4;
659 } 623 }
660 if (atomic_read(&pSMBFile->wrtPending))
661 cERROR(1, ("close with pending write"));
662 if (!pTcon->need_reconnect && 624 if (!pTcon->need_reconnect &&
663 !pSMBFile->invalidHandle) 625 !pSMBFile->invalidHandle)
664 rc = CIFSSMBClose(xid, pTcon, 626 rc = CIFSSMBClose(xid, pTcon,
@@ -681,24 +643,7 @@ int cifs_close(struct inode *inode, struct file *file)
681 list_del(&pSMBFile->flist); 643 list_del(&pSMBFile->flist);
682 list_del(&pSMBFile->tlist); 644 list_del(&pSMBFile->tlist);
683 write_unlock(&GlobalSMBSeslock); 645 write_unlock(&GlobalSMBSeslock);
684 timeout = 10; 646 cifsFileInfo_put(file->private_data);
685 /* We waited above to give the SMBWrite a chance to issue
686 on the wire (so we do not get SMBWrite returning EBADF
687 if writepages is racing with close. Note that writepages
688 does not specify a file handle, so it is possible for a file
689 to be opened twice, and the application close the "wrong"
690 file handle - in these cases we delay long enough to allow
691 the SMBWrite to get on the wire before the SMB Close.
692 We allow total wait here over 45 seconds, more than
693 oplock break time, and more than enough to allow any write
694 to complete on the server, or to time out on the client */
695 while ((atomic_read(&pSMBFile->wrtPending) != 0)
696 && (timeout <= 50000)) {
697 cERROR(1, ("writes pending, delay free of handle"));
698 msleep(timeout);
699 timeout *= 8;
700 }
701 kfree(file->private_data);
702 file->private_data = NULL; 647 file->private_data = NULL;
703 } else 648 } else
704 rc = -EBADF; 649 rc = -EBADF;
@@ -1236,7 +1181,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
1236 if (!open_file->invalidHandle) { 1181 if (!open_file->invalidHandle) {
1237 /* found a good file */ 1182 /* found a good file */
1238 /* lock it so it will not be closed on us */ 1183 /* lock it so it will not be closed on us */
1239 atomic_inc(&open_file->wrtPending); 1184 cifsFileInfo_get(open_file);
1240 read_unlock(&GlobalSMBSeslock); 1185 read_unlock(&GlobalSMBSeslock);
1241 return open_file; 1186 return open_file;
1242 } /* else might as well continue, and look for 1187 } /* else might as well continue, and look for
@@ -1276,7 +1221,7 @@ refind_writable:
1276 if (open_file->pfile && 1221 if (open_file->pfile &&
1277 ((open_file->pfile->f_flags & O_RDWR) || 1222 ((open_file->pfile->f_flags & O_RDWR) ||
1278 (open_file->pfile->f_flags & O_WRONLY))) { 1223 (open_file->pfile->f_flags & O_WRONLY))) {
1279 atomic_inc(&open_file->wrtPending); 1224 cifsFileInfo_get(open_file);
1280 1225
1281 if (!open_file->invalidHandle) { 1226 if (!open_file->invalidHandle) {
1282 /* found a good writable file */ 1227 /* found a good writable file */
@@ -1293,7 +1238,7 @@ refind_writable:
1293 else { /* start over in case this was deleted */ 1238 else { /* start over in case this was deleted */
1294 /* since the list could be modified */ 1239 /* since the list could be modified */
1295 read_lock(&GlobalSMBSeslock); 1240 read_lock(&GlobalSMBSeslock);
1296 atomic_dec(&open_file->wrtPending); 1241 cifsFileInfo_put(open_file);
1297 goto refind_writable; 1242 goto refind_writable;
1298 } 1243 }
1299 } 1244 }
@@ -1309,7 +1254,7 @@ refind_writable:
1309 read_lock(&GlobalSMBSeslock); 1254 read_lock(&GlobalSMBSeslock);
1310 /* can not use this handle, no write 1255 /* can not use this handle, no write
1311 pending on this one after all */ 1256 pending on this one after all */
1312 atomic_dec(&open_file->wrtPending); 1257 cifsFileInfo_put(open_file);
1313 1258
1314 if (open_file->closePend) /* list could have changed */ 1259 if (open_file->closePend) /* list could have changed */
1315 goto refind_writable; 1260 goto refind_writable;
@@ -1373,7 +1318,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1373 if (open_file) { 1318 if (open_file) {
1374 bytes_written = cifs_write(open_file->pfile, write_data, 1319 bytes_written = cifs_write(open_file->pfile, write_data,
1375 to-from, &offset); 1320 to-from, &offset);
1376 atomic_dec(&open_file->wrtPending); 1321 cifsFileInfo_put(open_file);
1377 /* Does mm or vfs already set times? */ 1322 /* Does mm or vfs already set times? */
1378 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb); 1323 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
1379 if ((bytes_written > 0) && (offset)) 1324 if ((bytes_written > 0) && (offset))
@@ -1562,7 +1507,7 @@ retry:
1562 bytes_to_write, offset, 1507 bytes_to_write, offset,
1563 &bytes_written, iov, n_iov, 1508 &bytes_written, iov, n_iov,
1564 long_op); 1509 long_op);
1565 atomic_dec(&open_file->wrtPending); 1510 cifsFileInfo_put(open_file);
1566 cifs_update_eof(cifsi, offset, bytes_written); 1511 cifs_update_eof(cifsi, offset, bytes_written);
1567 1512
1568 if (rc || bytes_written < bytes_to_write) { 1513 if (rc || bytes_written < bytes_to_write) {
@@ -2329,6 +2274,73 @@ out:
2329 return rc; 2274 return rc;
2330} 2275}
2331 2276
2277static void
2278cifs_oplock_break(struct slow_work *work)
2279{
2280 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
2281 oplock_break);
2282 struct inode *inode = cfile->pInode;
2283 struct cifsInodeInfo *cinode = CIFS_I(inode);
2284 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->mnt->mnt_sb);
2285 int rc, waitrc = 0;
2286
2287 if (inode && S_ISREG(inode->i_mode)) {
2288#ifdef CONFIG_CIFS_EXPERIMENTAL
2289 if (cinode->clientCanCacheAll == 0)
2290 break_lease(inode, FMODE_READ);
2291 else if (cinode->clientCanCacheRead == 0)
2292 break_lease(inode, FMODE_WRITE);
2293#endif
2294 rc = filemap_fdatawrite(inode->i_mapping);
2295 if (cinode->clientCanCacheRead == 0) {
2296 waitrc = filemap_fdatawait(inode->i_mapping);
2297 invalidate_remote_inode(inode);
2298 }
2299 if (!rc)
2300 rc = waitrc;
2301 if (rc)
2302 cinode->write_behind_rc = rc;
2303 cFYI(1, ("Oplock flush inode %p rc %d", inode, rc));
2304 }
2305
2306 /*
2307 * releasing stale oplock after recent reconnect of smb session using
2308 * a now incorrect file handle is not a data integrity issue but do
2309 * not bother sending an oplock release if session to server still is
2310 * disconnected since oplock already released by the server
2311 */
2312 if (!cfile->closePend && !cfile->oplock_break_cancelled) {
2313 rc = CIFSSMBLock(0, cifs_sb->tcon, cfile->netfid, 0, 0, 0, 0,
2314 LOCKING_ANDX_OPLOCK_RELEASE, false);
2315 cFYI(1, ("Oplock release rc = %d", rc));
2316 }
2317}
2318
2319static int
2320cifs_oplock_break_get(struct slow_work *work)
2321{
2322 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
2323 oplock_break);
2324 mntget(cfile->mnt);
2325 cifsFileInfo_get(cfile);
2326 return 0;
2327}
2328
2329static void
2330cifs_oplock_break_put(struct slow_work *work)
2331{
2332 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
2333 oplock_break);
2334 mntput(cfile->mnt);
2335 cifsFileInfo_put(cfile);
2336}
2337
2338const struct slow_work_ops cifs_oplock_break_ops = {
2339 .get_ref = cifs_oplock_break_get,
2340 .put_ref = cifs_oplock_break_put,
2341 .execute = cifs_oplock_break,
2342};
2343
2332const struct address_space_operations cifs_addr_ops = { 2344const struct address_space_operations cifs_addr_ops = {
2333 .readpage = cifs_readpage, 2345 .readpage = cifs_readpage,
2334 .readpages = cifs_readpages, 2346 .readpages = cifs_readpages,