diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 8add25538a3b..5ed03e0b8b40 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -2599,7 +2599,7 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov, | |||
2599 | ssize_t err; | 2599 | ssize_t err; |
2600 | 2600 | ||
2601 | err = generic_write_sync(file, iocb->ki_pos - rc, rc); | 2601 | err = generic_write_sync(file, iocb->ki_pos - rc, rc); |
2602 | if (rc < 0) | 2602 | if (err < 0) |
2603 | rc = err; | 2603 | rc = err; |
2604 | } | 2604 | } |
2605 | } else { | 2605 | } else { |
@@ -2621,12 +2621,20 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, | |||
2621 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | 2621 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
2622 | ssize_t written; | 2622 | ssize_t written; |
2623 | 2623 | ||
2624 | written = cifs_get_writer(cinode); | ||
2625 | if (written) | ||
2626 | return written; | ||
2627 | |||
2624 | if (CIFS_CACHE_WRITE(cinode)) { | 2628 | if (CIFS_CACHE_WRITE(cinode)) { |
2625 | if (cap_unix(tcon->ses) && | 2629 | if (cap_unix(tcon->ses) && |
2626 | (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) | 2630 | (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) |
2627 | && ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) | 2631 | && ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) { |
2628 | return generic_file_aio_write(iocb, iov, nr_segs, pos); | 2632 | written = generic_file_aio_write( |
2629 | return cifs_writev(iocb, iov, nr_segs, pos); | 2633 | iocb, iov, nr_segs, pos); |
2634 | goto out; | ||
2635 | } | ||
2636 | written = cifs_writev(iocb, iov, nr_segs, pos); | ||
2637 | goto out; | ||
2630 | } | 2638 | } |
2631 | /* | 2639 | /* |
2632 | * For non-oplocked files in strict cache mode we need to write the data | 2640 | * For non-oplocked files in strict cache mode we need to write the data |
@@ -2646,6 +2654,8 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, | |||
2646 | inode); | 2654 | inode); |
2647 | cinode->oplock = 0; | 2655 | cinode->oplock = 0; |
2648 | } | 2656 | } |
2657 | out: | ||
2658 | cifs_put_writer(cinode); | ||
2649 | return written; | 2659 | return written; |
2650 | } | 2660 | } |
2651 | 2661 | ||
@@ -2872,7 +2882,7 @@ ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, | |||
2872 | cifs_uncached_readv_complete); | 2882 | cifs_uncached_readv_complete); |
2873 | if (!rdata) { | 2883 | if (!rdata) { |
2874 | rc = -ENOMEM; | 2884 | rc = -ENOMEM; |
2875 | goto error; | 2885 | break; |
2876 | } | 2886 | } |
2877 | 2887 | ||
2878 | rc = cifs_read_allocate_pages(rdata, npages); | 2888 | rc = cifs_read_allocate_pages(rdata, npages); |
@@ -3621,6 +3631,13 @@ static int cifs_launder_page(struct page *page) | |||
3621 | return rc; | 3631 | return rc; |
3622 | } | 3632 | } |
3623 | 3633 | ||
3634 | static int | ||
3635 | cifs_pending_writers_wait(void *unused) | ||
3636 | { | ||
3637 | schedule(); | ||
3638 | return 0; | ||
3639 | } | ||
3640 | |||
3624 | void cifs_oplock_break(struct work_struct *work) | 3641 | void cifs_oplock_break(struct work_struct *work) |
3625 | { | 3642 | { |
3626 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, | 3643 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, |
@@ -3628,8 +3645,15 @@ void cifs_oplock_break(struct work_struct *work) | |||
3628 | struct inode *inode = cfile->dentry->d_inode; | 3645 | struct inode *inode = cfile->dentry->d_inode; |
3629 | struct cifsInodeInfo *cinode = CIFS_I(inode); | 3646 | struct cifsInodeInfo *cinode = CIFS_I(inode); |
3630 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | 3647 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
3648 | struct TCP_Server_Info *server = tcon->ses->server; | ||
3631 | int rc = 0; | 3649 | int rc = 0; |
3632 | 3650 | ||
3651 | wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS, | ||
3652 | cifs_pending_writers_wait, TASK_UNINTERRUPTIBLE); | ||
3653 | |||
3654 | server->ops->downgrade_oplock(server, cinode, | ||
3655 | test_bit(CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, &cinode->flags)); | ||
3656 | |||
3633 | if (!CIFS_CACHE_WRITE(cinode) && CIFS_CACHE_READ(cinode) && | 3657 | if (!CIFS_CACHE_WRITE(cinode) && CIFS_CACHE_READ(cinode) && |
3634 | cifs_has_mand_locks(cinode)) { | 3658 | cifs_has_mand_locks(cinode)) { |
3635 | cifs_dbg(FYI, "Reset oplock to None for inode=%p due to mand locks\n", | 3659 | cifs_dbg(FYI, "Reset oplock to None for inode=%p due to mand locks\n", |
@@ -3666,6 +3690,7 @@ void cifs_oplock_break(struct work_struct *work) | |||
3666 | cinode); | 3690 | cinode); |
3667 | cifs_dbg(FYI, "Oplock release rc = %d\n", rc); | 3691 | cifs_dbg(FYI, "Oplock release rc = %d\n", rc); |
3668 | } | 3692 | } |
3693 | cifs_done_oplock_break(cinode); | ||
3669 | } | 3694 | } |
3670 | 3695 | ||
3671 | /* | 3696 | /* |