diff options
| -rw-r--r-- | fs/cifs/cifsfs.c | 1 | ||||
| -rw-r--r-- | fs/cifs/cifsglob.h | 1 | ||||
| -rw-r--r-- | fs/cifs/file.c | 94 |
3 files changed, 31 insertions, 65 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index f653835d067b..de7f9168a118 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -228,7 +228,6 @@ cifs_alloc_inode(struct super_block *sb) | |||
| 228 | cifs_set_oplock_level(cifs_inode, 0); | 228 | cifs_set_oplock_level(cifs_inode, 0); |
| 229 | cifs_inode->delete_pending = false; | 229 | cifs_inode->delete_pending = false; |
| 230 | cifs_inode->invalid_mapping = false; | 230 | cifs_inode->invalid_mapping = false; |
| 231 | cifs_inode->leave_pages_clean = false; | ||
| 232 | cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ | 231 | cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ |
| 233 | cifs_inode->server_eof = 0; | 232 | cifs_inode->server_eof = 0; |
| 234 | cifs_inode->uniqueid = 0; | 233 | cifs_inode->uniqueid = 0; |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index aea1eec64911..dfab450a191e 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -1030,7 +1030,6 @@ struct cifsInodeInfo { | |||
| 1030 | bool clientCanCacheAll; /* read and writebehind oplock */ | 1030 | bool clientCanCacheAll; /* read and writebehind oplock */ |
| 1031 | bool delete_pending; /* DELETE_ON_CLOSE is set */ | 1031 | bool delete_pending; /* DELETE_ON_CLOSE is set */ |
| 1032 | bool invalid_mapping; /* pagecache is invalid */ | 1032 | bool invalid_mapping; /* pagecache is invalid */ |
| 1033 | bool leave_pages_clean; /* protected by i_mutex, not set pages dirty */ | ||
| 1034 | unsigned long time; /* jiffies of last update of inode */ | 1033 | unsigned long time; /* jiffies of last update of inode */ |
| 1035 | u64 server_eof; /* current file size on server -- protected by i_lock */ | 1034 | u64 server_eof; /* current file size on server -- protected by i_lock */ |
| 1036 | u64 uniqueid; /* server inode number */ | 1035 | u64 uniqueid; /* server inode number */ |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 0a6677ba212b..1b322d041f1e 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -2103,15 +2103,7 @@ static int cifs_write_end(struct file *file, struct address_space *mapping, | |||
| 2103 | } else { | 2103 | } else { |
| 2104 | rc = copied; | 2104 | rc = copied; |
| 2105 | pos += copied; | 2105 | pos += copied; |
| 2106 | /* | 2106 | set_page_dirty(page); |
| 2107 | * When we use strict cache mode and cifs_strict_writev was run | ||
| 2108 | * with level II oplock (indicated by leave_pages_clean field of | ||
| 2109 | * CIFS_I(inode)), we can leave pages clean - cifs_strict_writev | ||
| 2110 | * sent the data to the server itself. | ||
| 2111 | */ | ||
| 2112 | if (!CIFS_I(inode)->leave_pages_clean || | ||
| 2113 | !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)) | ||
| 2114 | set_page_dirty(page); | ||
| 2115 | } | 2107 | } |
| 2116 | 2108 | ||
| 2117 | if (rc > 0) { | 2109 | if (rc > 0) { |
| @@ -2462,8 +2454,8 @@ ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, | |||
| 2462 | } | 2454 | } |
| 2463 | 2455 | ||
| 2464 | static ssize_t | 2456 | static ssize_t |
| 2465 | cifs_pagecache_writev(struct kiocb *iocb, const struct iovec *iov, | 2457 | cifs_writev(struct kiocb *iocb, const struct iovec *iov, |
| 2466 | unsigned long nr_segs, loff_t pos, bool cache_ex) | 2458 | unsigned long nr_segs, loff_t pos) |
| 2467 | { | 2459 | { |
| 2468 | struct file *file = iocb->ki_filp; | 2460 | struct file *file = iocb->ki_filp; |
| 2469 | struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; | 2461 | struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; |
| @@ -2485,12 +2477,8 @@ cifs_pagecache_writev(struct kiocb *iocb, const struct iovec *iov, | |||
| 2485 | server->vals->exclusive_lock_type, NULL, | 2477 | server->vals->exclusive_lock_type, NULL, |
| 2486 | CIFS_WRITE_OP)) { | 2478 | CIFS_WRITE_OP)) { |
| 2487 | mutex_lock(&inode->i_mutex); | 2479 | mutex_lock(&inode->i_mutex); |
| 2488 | if (!cache_ex) | ||
| 2489 | cinode->leave_pages_clean = true; | ||
| 2490 | rc = __generic_file_aio_write(iocb, iov, nr_segs, | 2480 | rc = __generic_file_aio_write(iocb, iov, nr_segs, |
| 2491 | &iocb->ki_pos); | 2481 | &iocb->ki_pos); |
| 2492 | if (!cache_ex) | ||
| 2493 | cinode->leave_pages_clean = false; | ||
| 2494 | mutex_unlock(&inode->i_mutex); | 2482 | mutex_unlock(&inode->i_mutex); |
| 2495 | } | 2483 | } |
| 2496 | 2484 | ||
| @@ -2517,62 +2505,42 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, | |||
| 2517 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) | 2505 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) |
| 2518 | iocb->ki_filp->private_data; | 2506 | iocb->ki_filp->private_data; |
| 2519 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | 2507 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
| 2520 | ssize_t written, written2; | 2508 | |
| 2509 | #ifdef CONFIG_CIFS_SMB2 | ||
| 2521 | /* | 2510 | /* |
| 2522 | * We need to store clientCanCacheAll here to prevent race | 2511 | * If we have an oplock for read and want to write a data to the file |
| 2523 | * conditions - this value can be changed during an execution | 2512 | * we need to store it in the page cache and then push it to the server |
| 2524 | * of generic_file_aio_write. For CIFS it can be changed from | 2513 | * to be sure the next read will get a valid data. |
| 2525 | * true to false only, but for SMB2 it can be changed both from | ||
| 2526 | * true to false and vice versa. So, we can end up with a data | ||
| 2527 | * stored in the cache, not marked dirty and not sent to the | ||
| 2528 | * server if this value changes its state from false to true | ||
| 2529 | * after cifs_write_end. | ||
| 2530 | */ | 2514 | */ |
| 2531 | bool cache_ex = cinode->clientCanCacheAll; | 2515 | if (!cinode->clientCanCacheAll && cinode->clientCanCacheRead) { |
| 2532 | bool cache_read = cinode->clientCanCacheRead; | 2516 | ssize_t written; |
| 2533 | int rc; | 2517 | int rc; |
| 2534 | loff_t saved_pos; | 2518 | |
| 2519 | written = generic_file_aio_write(iocb, iov, nr_segs, pos); | ||
| 2520 | rc = filemap_fdatawrite(inode->i_mapping); | ||
| 2521 | if (rc) | ||
| 2522 | return (ssize_t)rc; | ||
| 2535 | 2523 | ||
| 2536 | if (cache_ex) { | 2524 | return written; |
| 2537 | if (cap_unix(tcon->ses) && | ||
| 2538 | ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0) && | ||
| 2539 | (CIFS_UNIX_FCNTL_CAP & le64_to_cpu( | ||
| 2540 | tcon->fsUnixInfo.Capability))) | ||
| 2541 | return generic_file_aio_write(iocb, iov, nr_segs, pos); | ||
| 2542 | return cifs_pagecache_writev(iocb, iov, nr_segs, pos, cache_ex); | ||
| 2543 | } | 2525 | } |
| 2526 | #endif | ||
| 2544 | 2527 | ||
| 2545 | /* | 2528 | /* |
| 2546 | * For files without exclusive oplock in strict cache mode we need to | 2529 | * For non-oplocked files in strict cache mode we need to write the data |
| 2547 | * write the data to the server exactly from the pos to pos+len-1 rather | 2530 | * to the server exactly from the pos to pos+len-1 rather than flush all |
| 2548 | * than flush all affected pages because it may cause a error with | 2531 | * affected pages because it may cause a error with mandatory locks on |
| 2549 | * mandatory locks on these pages but not on the region from pos to | 2532 | * these pages but not on the region from pos to ppos+len-1. |
| 2550 | * ppos+len-1. | ||
| 2551 | */ | 2533 | */ |
| 2552 | written = cifs_user_writev(iocb, iov, nr_segs, pos); | ||
| 2553 | if (!cache_read || written <= 0) | ||
| 2554 | return written; | ||
| 2555 | 2534 | ||
| 2556 | saved_pos = iocb->ki_pos; | 2535 | if (!cinode->clientCanCacheAll) |
| 2557 | iocb->ki_pos = pos; | 2536 | return cifs_user_writev(iocb, iov, nr_segs, pos); |
| 2558 | /* we have a read oplock - need to store a data in the page cache */ | 2537 | |
| 2559 | if (cap_unix(tcon->ses) && | 2538 | if (cap_unix(tcon->ses) && |
| 2560 | ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0) && | 2539 | (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && |
| 2561 | (CIFS_UNIX_FCNTL_CAP & le64_to_cpu( | 2540 | ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) |
| 2562 | tcon->fsUnixInfo.Capability))) | 2541 | return generic_file_aio_write(iocb, iov, nr_segs, pos); |
| 2563 | written2 = generic_file_aio_write(iocb, iov, nr_segs, pos); | 2542 | |
| 2564 | else | 2543 | return cifs_writev(iocb, iov, nr_segs, pos); |
| 2565 | written2 = cifs_pagecache_writev(iocb, iov, nr_segs, pos, | ||
| 2566 | cache_ex); | ||
| 2567 | /* errors occured during writing - invalidate the page cache */ | ||
| 2568 | if (written2 < 0) { | ||
| 2569 | rc = cifs_invalidate_mapping(inode); | ||
| 2570 | if (rc) | ||
| 2571 | written = (ssize_t)rc; | ||
| 2572 | else | ||
| 2573 | iocb->ki_pos = saved_pos; | ||
| 2574 | } | ||
| 2575 | return written; | ||
| 2576 | } | 2544 | } |
| 2577 | 2545 | ||
| 2578 | static struct cifs_readdata * | 2546 | static struct cifs_readdata * |
