diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-16 23:27:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-16 23:27:56 -0400 |
commit | 4fc8adcfec3da639da76e8314c9ccefe5bf9a045 (patch) | |
tree | e07a2dea8acf04d8bbbecd4fd3a571653ecdd953 /fs/cifs | |
parent | 84588e7a5d8220446d677d7b909a20ee7a4496b9 (diff) | |
parent | aa4d86163e4e91a1ac560954a554bab417e338f4 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull third hunk of vfs changes from Al Viro:
"This contains the ->direct_IO() changes from Omar + saner
generic_write_checks() + dealing with fcntl()/{read,write}() races
(mirroring O_APPEND/O_DIRECT into iocb->ki_flags and instead of
repeatedly looking at ->f_flags, which can be changed by fcntl(2),
check ->ki_flags - which cannot) + infrastructure bits for dhowells'
d_inode annotations + Christophs switch of /dev/loop to
vfs_iter_write()"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (30 commits)
block: loop: switch to VFS ITER_BVEC
configfs: Fix inconsistent use of file_inode() vs file->f_path.dentry->d_inode
VFS: Make pathwalk use d_is_reg() rather than S_ISREG()
VFS: Fix up debugfs to use d_is_dir() in place of S_ISDIR()
VFS: Combine inode checks with d_is_negative() and d_is_positive() in pathwalk
NFS: Don't use d_inode as a variable name
VFS: Impose ordering on accesses of d_inode and d_flags
VFS: Add owner-filesystem positive/negative dentry checks
nfs: generic_write_checks() shouldn't be done on swapout...
ocfs2: use __generic_file_write_iter()
mirror O_APPEND and O_DIRECT into iocb->ki_flags
switch generic_write_checks() to iocb and iter
ocfs2: move generic_write_checks() before the alignment checks
ocfs2_file_write_iter: stop messing with ppos
udf_file_write_iter: reorder and simplify
fuse: ->direct_IO() doesn't need generic_write_checks()
ext4_file_write_iter: move generic_write_checks() up
xfs_file_aio_write_checks: switch to iocb/iov_iter
generic_write_checks(): drop isblk argument
blkdev_write_iter: expand generic_file_checks() call in there
...
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/file.c | 93 |
1 files changed, 35 insertions, 58 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index ca30c391a894..ca2bc5406306 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -2560,10 +2560,9 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, | |||
2560 | return rc; | 2560 | return rc; |
2561 | } | 2561 | } |
2562 | 2562 | ||
2563 | static ssize_t | 2563 | ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) |
2564 | cifs_iovec_write(struct file *file, struct iov_iter *from, loff_t *poffset) | ||
2565 | { | 2564 | { |
2566 | size_t len; | 2565 | struct file *file = iocb->ki_filp; |
2567 | ssize_t total_written = 0; | 2566 | ssize_t total_written = 0; |
2568 | struct cifsFileInfo *open_file; | 2567 | struct cifsFileInfo *open_file; |
2569 | struct cifs_tcon *tcon; | 2568 | struct cifs_tcon *tcon; |
@@ -2573,15 +2572,15 @@ cifs_iovec_write(struct file *file, struct iov_iter *from, loff_t *poffset) | |||
2573 | struct iov_iter saved_from; | 2572 | struct iov_iter saved_from; |
2574 | int rc; | 2573 | int rc; |
2575 | 2574 | ||
2576 | len = iov_iter_count(from); | 2575 | /* |
2577 | rc = generic_write_checks(file, poffset, &len, 0); | 2576 | * BB - optimize the way when signing is disabled. We can drop this |
2578 | if (rc) | 2577 | * extra memory-to-memory copying and use iovec buffers for constructing |
2579 | return rc; | 2578 | * write request. |
2580 | 2579 | */ | |
2581 | if (!len) | ||
2582 | return 0; | ||
2583 | 2580 | ||
2584 | iov_iter_truncate(from, len); | 2581 | rc = generic_write_checks(iocb, from); |
2582 | if (rc <= 0) | ||
2583 | return rc; | ||
2585 | 2584 | ||
2586 | INIT_LIST_HEAD(&wdata_list); | 2585 | INIT_LIST_HEAD(&wdata_list); |
2587 | cifs_sb = CIFS_FILE_SB(file); | 2586 | cifs_sb = CIFS_FILE_SB(file); |
@@ -2593,8 +2592,8 @@ cifs_iovec_write(struct file *file, struct iov_iter *from, loff_t *poffset) | |||
2593 | 2592 | ||
2594 | memcpy(&saved_from, from, sizeof(struct iov_iter)); | 2593 | memcpy(&saved_from, from, sizeof(struct iov_iter)); |
2595 | 2594 | ||
2596 | rc = cifs_write_from_iter(*poffset, len, from, open_file, cifs_sb, | 2595 | rc = cifs_write_from_iter(iocb->ki_pos, iov_iter_count(from), from, |
2597 | &wdata_list); | 2596 | open_file, cifs_sb, &wdata_list); |
2598 | 2597 | ||
2599 | /* | 2598 | /* |
2600 | * If at least one write was successfully sent, then discard any rc | 2599 | * If at least one write was successfully sent, then discard any rc |
@@ -2633,7 +2632,7 @@ restart_loop: | |||
2633 | memcpy(&tmp_from, &saved_from, | 2632 | memcpy(&tmp_from, &saved_from, |
2634 | sizeof(struct iov_iter)); | 2633 | sizeof(struct iov_iter)); |
2635 | iov_iter_advance(&tmp_from, | 2634 | iov_iter_advance(&tmp_from, |
2636 | wdata->offset - *poffset); | 2635 | wdata->offset - iocb->ki_pos); |
2637 | 2636 | ||
2638 | rc = cifs_write_from_iter(wdata->offset, | 2637 | rc = cifs_write_from_iter(wdata->offset, |
2639 | wdata->bytes, &tmp_from, | 2638 | wdata->bytes, &tmp_from, |
@@ -2650,34 +2649,13 @@ restart_loop: | |||
2650 | kref_put(&wdata->refcount, cifs_uncached_writedata_release); | 2649 | kref_put(&wdata->refcount, cifs_uncached_writedata_release); |
2651 | } | 2650 | } |
2652 | 2651 | ||
2653 | if (total_written > 0) | 2652 | if (unlikely(!total_written)) |
2654 | *poffset += total_written; | 2653 | return rc; |
2655 | 2654 | ||
2655 | iocb->ki_pos += total_written; | ||
2656 | set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(file_inode(file))->flags); | ||
2656 | cifs_stats_bytes_written(tcon, total_written); | 2657 | cifs_stats_bytes_written(tcon, total_written); |
2657 | return total_written ? total_written : (ssize_t)rc; | 2658 | return total_written; |
2658 | } | ||
2659 | |||
2660 | ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) | ||
2661 | { | ||
2662 | ssize_t written; | ||
2663 | struct inode *inode; | ||
2664 | loff_t pos = iocb->ki_pos; | ||
2665 | |||
2666 | inode = file_inode(iocb->ki_filp); | ||
2667 | |||
2668 | /* | ||
2669 | * BB - optimize the way when signing is disabled. We can drop this | ||
2670 | * extra memory-to-memory copying and use iovec buffers for constructing | ||
2671 | * write request. | ||
2672 | */ | ||
2673 | |||
2674 | written = cifs_iovec_write(iocb->ki_filp, from, &pos); | ||
2675 | if (written > 0) { | ||
2676 | set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags); | ||
2677 | iocb->ki_pos = pos; | ||
2678 | } | ||
2679 | |||
2680 | return written; | ||
2681 | } | 2659 | } |
2682 | 2660 | ||
2683 | static ssize_t | 2661 | static ssize_t |
@@ -2688,8 +2666,7 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from) | |||
2688 | struct inode *inode = file->f_mapping->host; | 2666 | struct inode *inode = file->f_mapping->host; |
2689 | struct cifsInodeInfo *cinode = CIFS_I(inode); | 2667 | struct cifsInodeInfo *cinode = CIFS_I(inode); |
2690 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; | 2668 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; |
2691 | ssize_t rc = -EACCES; | 2669 | ssize_t rc; |
2692 | loff_t lock_pos = iocb->ki_pos; | ||
2693 | 2670 | ||
2694 | /* | 2671 | /* |
2695 | * We need to hold the sem to be sure nobody modifies lock list | 2672 | * We need to hold the sem to be sure nobody modifies lock list |
@@ -2697,23 +2674,24 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from) | |||
2697 | */ | 2674 | */ |
2698 | down_read(&cinode->lock_sem); | 2675 | down_read(&cinode->lock_sem); |
2699 | mutex_lock(&inode->i_mutex); | 2676 | mutex_lock(&inode->i_mutex); |
2700 | if (file->f_flags & O_APPEND) | 2677 | |
2701 | lock_pos = i_size_read(inode); | 2678 | rc = generic_write_checks(iocb, from); |
2702 | if (!cifs_find_lock_conflict(cfile, lock_pos, iov_iter_count(from), | 2679 | if (rc <= 0) |
2680 | goto out; | ||
2681 | |||
2682 | if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from), | ||
2703 | server->vals->exclusive_lock_type, NULL, | 2683 | server->vals->exclusive_lock_type, NULL, |
2704 | CIFS_WRITE_OP)) { | 2684 | CIFS_WRITE_OP)) |
2705 | rc = __generic_file_write_iter(iocb, from); | 2685 | rc = __generic_file_write_iter(iocb, from); |
2706 | mutex_unlock(&inode->i_mutex); | 2686 | else |
2707 | 2687 | rc = -EACCES; | |
2708 | if (rc > 0) { | 2688 | out: |
2709 | ssize_t err; | 2689 | mutex_unlock(&inode->i_mutex); |
2710 | 2690 | ||
2711 | err = generic_write_sync(file, iocb->ki_pos - rc, rc); | 2691 | if (rc > 0) { |
2712 | if (err < 0) | 2692 | ssize_t err = generic_write_sync(file, iocb->ki_pos - rc, rc); |
2713 | rc = err; | 2693 | if (err < 0) |
2714 | } | 2694 | rc = err; |
2715 | } else { | ||
2716 | mutex_unlock(&inode->i_mutex); | ||
2717 | } | 2695 | } |
2718 | up_read(&cinode->lock_sem); | 2696 | up_read(&cinode->lock_sem); |
2719 | return rc; | 2697 | return rc; |
@@ -3877,8 +3855,7 @@ void cifs_oplock_break(struct work_struct *work) | |||
3877 | * Direct IO is not yet supported in the cached mode. | 3855 | * Direct IO is not yet supported in the cached mode. |
3878 | */ | 3856 | */ |
3879 | static ssize_t | 3857 | static ssize_t |
3880 | cifs_direct_io(int rw, struct kiocb *iocb, struct iov_iter *iter, | 3858 | cifs_direct_io(struct kiocb *iocb, struct iov_iter *iter, loff_t pos) |
3881 | loff_t pos) | ||
3882 | { | 3859 | { |
3883 | /* | 3860 | /* |
3884 | * FIXME | 3861 | * FIXME |